[MTD] chips: Clean up trailing white spaces
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
e4f0648fb4
commit
1f948b43f7
@ -1,5 +1,5 @@
|
|||||||
# drivers/mtd/chips/Kconfig
|
# drivers/mtd/chips/Kconfig
|
||||||
# $Id: Kconfig,v 1.15 2005/06/06 23:04:35 tpoynor Exp $
|
# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $
|
||||||
|
|
||||||
menu "RAM/ROM/Flash chip drivers"
|
menu "RAM/ROM/Flash chip drivers"
|
||||||
depends on MTD!=n
|
depends on MTD!=n
|
||||||
@ -39,7 +39,7 @@ config MTD_CFI_ADV_OPTIONS
|
|||||||
If you need to specify a specific endianness for access to flash
|
If you need to specify a specific endianness for access to flash
|
||||||
chips, or if you wish to reduce the size of the kernel by including
|
chips, or if you wish to reduce the size of the kernel by including
|
||||||
support for only specific arrangements of flash chips, say 'Y'. This
|
support for only specific arrangements of flash chips, say 'Y'. This
|
||||||
option does not directly affect the code, but will enable other
|
option does not directly affect the code, but will enable other
|
||||||
configuration options which allow you to do so.
|
configuration options which allow you to do so.
|
||||||
|
|
||||||
If unsure, say 'N'.
|
If unsure, say 'N'.
|
||||||
@ -56,7 +56,7 @@ config MTD_CFI_NOSWAP
|
|||||||
data bits when writing the 'magic' commands to the chips. Saying
|
data bits when writing the 'magic' commands to the chips. Saying
|
||||||
'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't
|
'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't
|
||||||
enabled, means that the CPU will not do any swapping; the chips
|
enabled, means that the CPU will not do any swapping; the chips
|
||||||
are expected to be wired to the CPU in 'host-endian' form.
|
are expected to be wired to the CPU in 'host-endian' form.
|
||||||
Specific arrangements are possible with the BIG_ENDIAN_BYTE and
|
Specific arrangements are possible with the BIG_ENDIAN_BYTE and
|
||||||
LITTLE_ENDIAN_BYTE, if the bytes are reversed.
|
LITTLE_ENDIAN_BYTE, if the bytes are reversed.
|
||||||
|
|
||||||
@ -79,10 +79,10 @@ config MTD_CFI_GEOMETRY
|
|||||||
bool "Specific CFI Flash geometry selection"
|
bool "Specific CFI Flash geometry selection"
|
||||||
depends on MTD_CFI_ADV_OPTIONS
|
depends on MTD_CFI_ADV_OPTIONS
|
||||||
help
|
help
|
||||||
This option does not affect the code directly, but will enable
|
This option does not affect the code directly, but will enable
|
||||||
some other configuration options which would allow you to reduce
|
some other configuration options which would allow you to reduce
|
||||||
the size of the kernel by including support for only certain
|
the size of the kernel by including support for only certain
|
||||||
arrangements of CFI chips. If unsure, say 'N' and all options
|
arrangements of CFI chips. If unsure, say 'N' and all options
|
||||||
which are supported by the current code will be enabled.
|
which are supported by the current code will be enabled.
|
||||||
|
|
||||||
config MTD_MAP_BANK_WIDTH_1
|
config MTD_MAP_BANK_WIDTH_1
|
||||||
@ -197,7 +197,7 @@ config MTD_CFI_AMDSTD
|
|||||||
help
|
help
|
||||||
The Common Flash Interface defines a number of different command
|
The Common Flash Interface defines a number of different command
|
||||||
sets which a CFI-compliant chip may claim to implement. This code
|
sets which a CFI-compliant chip may claim to implement. This code
|
||||||
provides support for one of those command sets, used on chips
|
provides support for one of those command sets, used on chips
|
||||||
including the AMD Am29LV320.
|
including the AMD Am29LV320.
|
||||||
|
|
||||||
config MTD_CFI_AMDSTD_RETRY
|
config MTD_CFI_AMDSTD_RETRY
|
||||||
@ -237,14 +237,14 @@ config MTD_RAM
|
|||||||
tristate "Support for RAM chips in bus mapping"
|
tristate "Support for RAM chips in bus mapping"
|
||||||
depends on MTD
|
depends on MTD
|
||||||
help
|
help
|
||||||
This option enables basic support for RAM chips accessed through
|
This option enables basic support for RAM chips accessed through
|
||||||
a bus mapping driver.
|
a bus mapping driver.
|
||||||
|
|
||||||
config MTD_ROM
|
config MTD_ROM
|
||||||
tristate "Support for ROM chips in bus mapping"
|
tristate "Support for ROM chips in bus mapping"
|
||||||
depends on MTD
|
depends on MTD
|
||||||
help
|
help
|
||||||
This option enables basic support for ROM chips accessed through
|
This option enables basic support for ROM chips accessed through
|
||||||
a bus mapping driver.
|
a bus mapping driver.
|
||||||
|
|
||||||
config MTD_ABSENT
|
config MTD_ABSENT
|
||||||
@ -275,7 +275,7 @@ config MTD_AMDSTD
|
|||||||
depends on MTD && MTD_OBSOLETE_CHIPS
|
depends on MTD && MTD_OBSOLETE_CHIPS
|
||||||
help
|
help
|
||||||
This option enables support for flash chips using AMD-compatible
|
This option enables support for flash chips using AMD-compatible
|
||||||
commands, including some which are not CFI-compatible and hence
|
commands, including some which are not CFI-compatible and hence
|
||||||
cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
|
cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
|
||||||
|
|
||||||
It also works on AMD compatible chips that do conform to CFI.
|
It also works on AMD compatible chips that do conform to CFI.
|
||||||
@ -285,7 +285,7 @@ config MTD_SHARP
|
|||||||
depends on MTD && MTD_OBSOLETE_CHIPS
|
depends on MTD && MTD_OBSOLETE_CHIPS
|
||||||
help
|
help
|
||||||
This option enables support for flash chips using Sharp-compatible
|
This option enables support for flash chips using Sharp-compatible
|
||||||
commands, including some which are not CFI-compatible and hence
|
commands, including some which are not CFI-compatible and hence
|
||||||
cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
|
cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
|
||||||
|
|
||||||
config MTD_JEDEC
|
config MTD_JEDEC
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# linux/drivers/chips/Makefile
|
# linux/drivers/chips/Makefile
|
||||||
#
|
#
|
||||||
# $Id: Makefile.common,v 1.4 2004/07/12 16:07:30 dwmw2 Exp $
|
# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
|
||||||
|
|
||||||
# *** BIG UGLY NOTE ***
|
# *** BIG UGLY NOTE ***
|
||||||
#
|
#
|
||||||
@ -11,7 +11,7 @@
|
|||||||
# the CFI command set drivers are linked before gen_probe.o
|
# the CFI command set drivers are linked before gen_probe.o
|
||||||
|
|
||||||
obj-$(CONFIG_MTD) += chipreg.o
|
obj-$(CONFIG_MTD) += chipreg.o
|
||||||
obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
|
obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
|
||||||
obj-$(CONFIG_MTD_CFI) += cfi_probe.o
|
obj-$(CONFIG_MTD_CFI) += cfi_probe.o
|
||||||
obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o
|
obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o
|
||||||
obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
|
obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Author: Jonas Holmberg <jonas.holmberg@axis.com>
|
* Author: Jonas Holmberg <jonas.holmberg@axis.com>
|
||||||
*
|
*
|
||||||
* $Id: amd_flash.c,v 1.27 2005/02/04 07:43:09 jonashg Exp $
|
* $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001 Axis Communications AB
|
* Copyright (c) 2001 Axis Communications AB
|
||||||
*
|
*
|
||||||
@ -93,9 +93,9 @@
|
|||||||
#define D6_MASK 0x40
|
#define D6_MASK 0x40
|
||||||
|
|
||||||
struct amd_flash_private {
|
struct amd_flash_private {
|
||||||
int device_type;
|
int device_type;
|
||||||
int interleave;
|
int interleave;
|
||||||
int numchips;
|
int numchips;
|
||||||
unsigned long chipshift;
|
unsigned long chipshift;
|
||||||
// const char *im_name;
|
// const char *im_name;
|
||||||
struct flchip chips[0];
|
struct flchip chips[0];
|
||||||
@ -253,7 +253,7 @@ static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len,
|
|||||||
int i;
|
int i;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int lock_status;
|
int lock_status;
|
||||||
|
|
||||||
map = mtd->priv;
|
map = mtd->priv;
|
||||||
|
|
||||||
/* Pass the whole chip through sector by sector and check for each
|
/* Pass the whole chip through sector by sector and check for each
|
||||||
@ -273,7 +273,7 @@ static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len,
|
|||||||
unlock_sector(map, eraseoffset, is_unlock);
|
unlock_sector(map, eraseoffset, is_unlock);
|
||||||
|
|
||||||
lock_status = is_sector_locked(map, eraseoffset);
|
lock_status = is_sector_locked(map, eraseoffset);
|
||||||
|
|
||||||
if (is_unlock && lock_status) {
|
if (is_unlock && lock_status) {
|
||||||
printk("Cannot unlock sector at address %x length %xx\n",
|
printk("Cannot unlock sector at address %x length %xx\n",
|
||||||
eraseoffset, merip->erasesize);
|
eraseoffset, merip->erasesize);
|
||||||
@ -305,7 +305,7 @@ static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
/*
|
/*
|
||||||
* Reads JEDEC manufacturer ID and device ID and returns the index of the first
|
* Reads JEDEC manufacturer ID and device ID and returns the index of the first
|
||||||
* matching table entry (-1 if not found or alias for already found chip).
|
* matching table entry (-1 if not found or alias for already found chip).
|
||||||
*/
|
*/
|
||||||
static int probe_new_chip(struct mtd_info *mtd, __u32 base,
|
static int probe_new_chip(struct mtd_info *mtd, __u32 base,
|
||||||
struct flchip *chips,
|
struct flchip *chips,
|
||||||
struct amd_flash_private *private,
|
struct amd_flash_private *private,
|
||||||
@ -636,7 +636,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
|
|||||||
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
|
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
|
||||||
{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 }
|
{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mtd_info *mtd;
|
struct mtd_info *mtd;
|
||||||
@ -701,7 +701,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
|
|||||||
|
|
||||||
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
|
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
|
||||||
mtd->numeraseregions, GFP_KERNEL);
|
mtd->numeraseregions, GFP_KERNEL);
|
||||||
if (!mtd->eraseregions) {
|
if (!mtd->eraseregions) {
|
||||||
printk(KERN_WARNING "%s: Failed to allocate "
|
printk(KERN_WARNING "%s: Failed to allocate "
|
||||||
"memory for MTD erase region info\n", map->name);
|
"memory for MTD erase region info\n", map->name);
|
||||||
kfree(mtd);
|
kfree(mtd);
|
||||||
@ -739,12 +739,12 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
|
|||||||
mtd->type = MTD_NORFLASH;
|
mtd->type = MTD_NORFLASH;
|
||||||
mtd->flags = MTD_CAP_NORFLASH;
|
mtd->flags = MTD_CAP_NORFLASH;
|
||||||
mtd->name = map->name;
|
mtd->name = map->name;
|
||||||
mtd->erase = amd_flash_erase;
|
mtd->erase = amd_flash_erase;
|
||||||
mtd->read = amd_flash_read;
|
mtd->read = amd_flash_read;
|
||||||
mtd->write = amd_flash_write;
|
mtd->write = amd_flash_write;
|
||||||
mtd->sync = amd_flash_sync;
|
mtd->sync = amd_flash_sync;
|
||||||
mtd->suspend = amd_flash_suspend;
|
mtd->suspend = amd_flash_suspend;
|
||||||
mtd->resume = amd_flash_resume;
|
mtd->resume = amd_flash_resume;
|
||||||
mtd->lock = amd_flash_lock;
|
mtd->lock = amd_flash_lock;
|
||||||
mtd->unlock = amd_flash_unlock;
|
mtd->unlock = amd_flash_unlock;
|
||||||
|
|
||||||
@ -789,7 +789,7 @@ retry:
|
|||||||
map->name, chip->state);
|
map->name, chip->state);
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
@ -802,7 +802,7 @@ retry:
|
|||||||
timeo = jiffies + HZ;
|
timeo = jiffies + HZ;
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
@ -889,7 +889,7 @@ retry:
|
|||||||
map->name, chip->state);
|
map->name, chip->state);
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
@ -901,7 +901,7 @@ retry:
|
|||||||
timeo = jiffies + HZ;
|
timeo = jiffies + HZ;
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->state = FL_WRITING;
|
chip->state = FL_WRITING;
|
||||||
|
|
||||||
@ -911,7 +911,7 @@ retry:
|
|||||||
wide_write(map, datum, adr);
|
wide_write(map, datum, adr);
|
||||||
|
|
||||||
times_left = 500000;
|
times_left = 500000;
|
||||||
while (times_left-- && flash_is_busy(map, adr, private->interleave)) {
|
while (times_left-- && flash_is_busy(map, adr, private->interleave)) {
|
||||||
if (need_resched()) {
|
if (need_resched()) {
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
schedule();
|
schedule();
|
||||||
@ -989,7 +989,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs += n;
|
ofs += n;
|
||||||
buf += n;
|
buf += n;
|
||||||
(*retlen) += n;
|
(*retlen) += n;
|
||||||
@ -1002,7 +1002,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are now aligned, write as much as possible. */
|
/* We are now aligned, write as much as possible. */
|
||||||
while(len >= map->buswidth) {
|
while(len >= map->buswidth) {
|
||||||
__u32 datum;
|
__u32 datum;
|
||||||
@ -1063,7 +1063,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*retlen) += n;
|
(*retlen) += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,7 +1085,7 @@ retry:
|
|||||||
if (chip->state != FL_READY){
|
if (chip->state != FL_READY){
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
@ -1098,7 +1098,7 @@ retry:
|
|||||||
timeo = jiffies + HZ;
|
timeo = jiffies + HZ;
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->state = FL_ERASING;
|
chip->state = FL_ERASING;
|
||||||
|
|
||||||
@ -1106,30 +1106,30 @@ retry:
|
|||||||
ENABLE_VPP(map);
|
ENABLE_VPP(map);
|
||||||
send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA);
|
send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA);
|
||||||
send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr);
|
send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr);
|
||||||
|
|
||||||
timeo = jiffies + (HZ * 20);
|
timeo = jiffies + (HZ * 20);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
while (flash_is_busy(map, adr, private->interleave)) {
|
while (flash_is_busy(map, adr, private->interleave)) {
|
||||||
|
|
||||||
if (chip->state != FL_ERASING) {
|
if (chip->state != FL_ERASING) {
|
||||||
/* Someone's suspended the erase. Sleep */
|
/* Someone's suspended the erase. Sleep */
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
printk(KERN_INFO "%s: erase suspended. Sleeping\n",
|
printk(KERN_INFO "%s: erase suspended. Sleeping\n",
|
||||||
map->name);
|
map->name);
|
||||||
schedule();
|
schedule();
|
||||||
remove_wait_queue(&chip->wq, &wait);
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
if (signal_pending(current)) {
|
if (signal_pending(current)) {
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = jiffies + (HZ*2); /* FIXME */
|
timeo = jiffies + (HZ*2); /* FIXME */
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
continue;
|
continue;
|
||||||
@ -1145,7 +1145,7 @@ retry:
|
|||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
|
|
||||||
@ -1153,7 +1153,7 @@ retry:
|
|||||||
schedule();
|
schedule();
|
||||||
else
|
else
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,7 +1180,7 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DISABLE_VPP(map);
|
DISABLE_VPP(map);
|
||||||
chip->state = FL_READY;
|
chip->state = FL_READY;
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
@ -1246,7 +1246,7 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
* with the erase region at that address.
|
* with the erase region at that address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while ((i < mtd->numeraseregions) &&
|
while ((i < mtd->numeraseregions) &&
|
||||||
((instr->addr + instr->len) >= regions[i].offset)) {
|
((instr->addr + instr->len) >= regions[i].offset)) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -1293,10 +1293,10 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1324,7 +1324,7 @@ static void amd_flash_sync(struct mtd_info *mtd)
|
|||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_SYNCING;
|
chip->state = FL_SYNCING;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1335,13 +1335,13 @@ static void amd_flash_sync(struct mtd_info *mtd)
|
|||||||
default:
|
default:
|
||||||
/* Not an idle state */
|
/* Not an idle state */
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
|
|
||||||
remove_wait_queue(&chip->wq, &wait);
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1351,7 +1351,7 @@ static void amd_flash_sync(struct mtd_info *mtd)
|
|||||||
chip = &private->chips[i];
|
chip = &private->chips[i];
|
||||||
|
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_SYNCING) {
|
if (chip->state == FL_SYNCING) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
*
|
*
|
||||||
* (C) 2000 Red Hat. GPL'd
|
* (C) 2000 Red Hat. GPL'd
|
||||||
*
|
*
|
||||||
* $Id: cfi_cmdset_0001.c,v 1.184 2005/10/25 20:28:40 nico Exp $
|
* $Id: cfi_cmdset_0001.c,v 1.185 2005/11/07 11:14:22 gleixner Exp $
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* 10/10/2000 Nicolas Pitre <nico@cam.org>
|
* 10/10/2000 Nicolas Pitre <nico@cam.org>
|
||||||
* - completely revamped method functions so they are aware and
|
* - completely revamped method functions so they are aware and
|
||||||
* independent of the flash geometry (buswidth, interleave, etc.)
|
* independent of the flash geometry (buswidth, interleave, etc.)
|
||||||
@ -120,17 +120,17 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||||||
printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
|
printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
|
||||||
printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported");
|
printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported");
|
||||||
for (i=11; i<32; i++) {
|
for (i=11; i<32; i++) {
|
||||||
if (extp->FeatureSupport & (1<<i))
|
if (extp->FeatureSupport & (1<<i))
|
||||||
printk(" - Unknown Bit %X: supported\n", i);
|
printk(" - Unknown Bit %X: supported\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
|
printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
|
||||||
printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
|
printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
|
||||||
for (i=1; i<8; i++) {
|
for (i=1; i<8; i++) {
|
||||||
if (extp->SuspendCmdSupport & (1<<i))
|
if (extp->SuspendCmdSupport & (1<<i))
|
||||||
printk(" - Unknown Bit %X: supported\n", i);
|
printk(" - Unknown Bit %X: supported\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
|
printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
|
||||||
printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
|
printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
|
||||||
printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
|
printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
|
||||||
@ -145,16 +145,16 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||||||
printk(" - Unknown Bit %X Active: yes\n",i);
|
printk(" - Unknown Bit %X Active: yes\n",i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VccOptimal >> 4, extp->VccOptimal & 0xf);
|
extp->VccOptimal >> 4, extp->VccOptimal & 0xf);
|
||||||
if (extp->VppOptimal)
|
if (extp->VppOptimal)
|
||||||
printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VppOptimal >> 4, extp->VppOptimal & 0xf);
|
extp->VppOptimal >> 4, extp->VppOptimal & 0xf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
||||||
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
|
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
|
||||||
static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
|
static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
@ -185,7 +185,7 @@ static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
|
|||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
|
||||||
cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */
|
cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */
|
||||||
cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
|
cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
|
|||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
|
||||||
/* Note this is done after the region info is endian swapped */
|
/* Note this is done after the region info is endian swapped */
|
||||||
cfi->cfiq->EraseRegionInfo[1] =
|
cfi->cfiq->EraseRegionInfo[1] =
|
||||||
(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
|
(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
|
||||||
@ -222,7 +222,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
|||||||
|
|
||||||
static struct cfi_fixup cfi_fixup_table[] = {
|
static struct cfi_fixup cfi_fixup_table[] = {
|
||||||
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
||||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
|
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
|
||||||
#endif
|
#endif
|
||||||
#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
|
#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
|
||||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL },
|
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL },
|
||||||
@ -327,7 +327,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return extp;
|
return extp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
|
|||||||
mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
|
mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
|
||||||
|
|
||||||
if (cfi->cfi_mode == CFI_MODE_CFI) {
|
if (cfi->cfi_mode == CFI_MODE_CFI) {
|
||||||
/*
|
/*
|
||||||
* It's a real CFI chip, not one for which the probe
|
* It's a real CFI chip, not one for which the probe
|
||||||
* routine faked a CFI structure. So we read the feature
|
* routine faked a CFI structure. So we read the feature
|
||||||
* table from it.
|
* table from it.
|
||||||
@ -383,14 +383,14 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Install our own private info structure */
|
/* Install our own private info structure */
|
||||||
cfi->cmdset_priv = extp;
|
cfi->cmdset_priv = extp;
|
||||||
|
|
||||||
cfi_fixup(mtd, cfi_fixup_table);
|
cfi_fixup(mtd, cfi_fixup_table);
|
||||||
|
|
||||||
#ifdef DEBUG_CFI_FEATURES
|
#ifdef DEBUG_CFI_FEATURES
|
||||||
/* Tell the user about it in lots of lovely detail */
|
/* Tell the user about it in lots of lovely detail */
|
||||||
cfi_tell_features(extp);
|
cfi_tell_features(extp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(extp->SuspendCmdSupport & 1) {
|
if(extp->SuspendCmdSupport & 1) {
|
||||||
printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
|
printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
|
||||||
@ -408,10 +408,10 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
|
|||||||
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
|
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
|
||||||
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
|
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
|
||||||
cfi->chips[i].ref_point_counter = 0;
|
cfi->chips[i].ref_point_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->fldrv = &cfi_intelext_chipdrv;
|
map->fldrv = &cfi_intelext_chipdrv;
|
||||||
|
|
||||||
return cfi_intelext_setup(mtd);
|
return cfi_intelext_setup(mtd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,13 +428,13 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
|
|||||||
mtd->size = devsize * cfi->numchips;
|
mtd->size = devsize * cfi->numchips;
|
||||||
|
|
||||||
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
||||||
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
||||||
* mtd->numeraseregions, GFP_KERNEL);
|
* mtd->numeraseregions, GFP_KERNEL);
|
||||||
if (!mtd->eraseregions) {
|
if (!mtd->eraseregions) {
|
||||||
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
|
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
|
||||||
goto setup_err;
|
goto setup_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
||||||
unsigned long ernum, ersize;
|
unsigned long ernum, ersize;
|
||||||
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
||||||
@ -701,7 +701,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n",
|
printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n",
|
||||||
map->name, status.x[0]);
|
map->name, status.x[0]);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -711,7 +711,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||||||
/* Someone else might have been playing with it. */
|
/* Someone else might have been playing with it. */
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FL_READY:
|
case FL_READY:
|
||||||
case FL_CFI_QUERY:
|
case FL_CFI_QUERY:
|
||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
@ -830,14 +830,14 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
|
|||||||
switch(chip->oldstate) {
|
switch(chip->oldstate) {
|
||||||
case FL_ERASING:
|
case FL_ERASING:
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
/* What if one interleaved chip has finished and the
|
/* What if one interleaved chip has finished and the
|
||||||
other hasn't? The old code would leave the finished
|
other hasn't? The old code would leave the finished
|
||||||
one in READY mode. That's bad, and caused -EROFS
|
one in READY mode. That's bad, and caused -EROFS
|
||||||
errors to be returned from do_erase_oneblock because
|
errors to be returned from do_erase_oneblock because
|
||||||
that's the only bit it checked for at the time.
|
that's the only bit it checked for at the time.
|
||||||
As the state machine appears to explicitly allow
|
As the state machine appears to explicitly allow
|
||||||
sending the 0x70 (Read Status) command to an erasing
|
sending the 0x70 (Read Status) command to an erasing
|
||||||
chip and expecting it to be ignored, that's what we
|
chip and expecting it to be ignored, that's what we
|
||||||
do. */
|
do. */
|
||||||
map_write(map, CMD(0xd0), adr);
|
map_write(map, CMD(0xd0), adr);
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1073,8 +1073,8 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
|
|||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
/* Ensure cmd read/writes are aligned. */
|
/* Ensure cmd read/writes are aligned. */
|
||||||
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
@ -1102,7 +1102,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
|
|||||||
|
|
||||||
if (!map->virt || (from + len > mtd->size))
|
if (!map->virt || (from + len > mtd->size))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*mtdbuf = (void *)map->virt + from;
|
*mtdbuf = (void *)map->virt + from;
|
||||||
*retlen = 0;
|
*retlen = 0;
|
||||||
|
|
||||||
@ -1129,7 +1129,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
|
|||||||
|
|
||||||
*retlen += thislen;
|
*retlen += thislen;
|
||||||
len -= thislen;
|
len -= thislen;
|
||||||
|
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
}
|
}
|
||||||
@ -1187,8 +1187,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
/* Ensure cmd read/writes are aligned. */
|
/* Ensure cmd read/writes are aligned. */
|
||||||
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
ret = get_chip(map, chip, cmd_addr, FL_READY);
|
ret = get_chip(map, chip, cmd_addr, FL_READY);
|
||||||
@ -1243,7 +1243,7 @@ static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, siz
|
|||||||
*retlen += thislen;
|
*retlen += thislen;
|
||||||
len -= thislen;
|
len -= thislen;
|
||||||
buf += thislen;
|
buf += thislen;
|
||||||
|
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
}
|
}
|
||||||
@ -1311,7 +1311,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1331,7 +1331,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
|||||||
if (!chip->word_write_time)
|
if (!chip->word_write_time)
|
||||||
chip->word_write_time = 1;
|
chip->word_write_time = 1;
|
||||||
}
|
}
|
||||||
if (z > 1)
|
if (z > 1)
|
||||||
chip->word_write_time++;
|
chip->word_write_time++;
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
@ -1394,7 +1394,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
|
|||||||
|
|
||||||
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
||||||
bus_ofs, datum, FL_WRITING);
|
bus_ofs, datum, FL_WRITING);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
len -= n;
|
len -= n;
|
||||||
@ -1403,13 +1403,13 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
|
|||||||
(*retlen) += n;
|
(*retlen) += n;
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while(len >= map_bankwidth(map)) {
|
while(len >= map_bankwidth(map)) {
|
||||||
map_word datum = map_word_load(map, buf);
|
map_word datum = map_word_load(map, buf);
|
||||||
|
|
||||||
@ -1424,7 +1424,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
|
|||||||
len -= map_bankwidth(map);
|
len -= map_bankwidth(map);
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1439,9 +1439,9 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
|
|||||||
|
|
||||||
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
||||||
ofs, datum, FL_WRITING);
|
ofs, datum, FL_WRITING);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
(*retlen) += len;
|
(*retlen) += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1449,7 +1449,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||||
unsigned long adr, const struct kvec **pvec,
|
unsigned long adr, const struct kvec **pvec,
|
||||||
unsigned long *pvec_seek, int len)
|
unsigned long *pvec_seek, int len)
|
||||||
{
|
{
|
||||||
@ -1480,7 +1480,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
xip_disable(map, chip, cmd_adr);
|
xip_disable(map, chip, cmd_adr);
|
||||||
|
|
||||||
/* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
|
/* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
|
||||||
[...], the device will not accept any more Write to Buffer commands".
|
[...], the device will not accept any more Write to Buffer commands".
|
||||||
So we must check here and reset those bits if they're set. Otherwise
|
So we must check here and reset those bits if they're set. Otherwise
|
||||||
we're just pissing in the wind */
|
we're just pissing in the wind */
|
||||||
if (chip->state != FL_STATUS)
|
if (chip->state != FL_STATUS)
|
||||||
@ -1549,9 +1549,9 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
|
|
||||||
if (!word_gap && len < map_bankwidth(map))
|
if (!word_gap && len < map_bankwidth(map))
|
||||||
datum = map_word_ff(map);
|
datum = map_word_ff(map);
|
||||||
|
|
||||||
datum = map_word_load_partial(map, datum,
|
datum = map_word_load_partial(map, datum,
|
||||||
vec->iov_base + vec_seek,
|
vec->iov_base + vec_seek,
|
||||||
word_gap, n);
|
word_gap, n);
|
||||||
|
|
||||||
len -= n;
|
len -= n;
|
||||||
@ -1575,7 +1575,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
map_write(map, CMD(0xd0), cmd_adr);
|
map_write(map, CMD(0xd0), cmd_adr);
|
||||||
chip->state = FL_WRITING;
|
chip->state = FL_WRITING;
|
||||||
|
|
||||||
INVALIDATE_CACHE_UDELAY(map, chip,
|
INVALIDATE_CACHE_UDELAY(map, chip,
|
||||||
cmd_adr, len,
|
cmd_adr, len,
|
||||||
chip->buffer_write_time);
|
chip->buffer_write_time);
|
||||||
|
|
||||||
@ -1608,7 +1608,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
z++;
|
z++;
|
||||||
UDELAY(map, chip, cmd_adr, 1);
|
UDELAY(map, chip, cmd_adr, 1);
|
||||||
@ -1618,7 +1618,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
if (!chip->buffer_write_time)
|
if (!chip->buffer_write_time)
|
||||||
chip->buffer_write_time = 1;
|
chip->buffer_write_time = 1;
|
||||||
}
|
}
|
||||||
if (z > 1)
|
if (z > 1)
|
||||||
chip->buffer_write_time++;
|
chip->buffer_write_time++;
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
@ -1680,7 +1680,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
|
|||||||
|
|
||||||
if (size > len)
|
if (size > len)
|
||||||
size = len;
|
size = len;
|
||||||
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
||||||
ofs, &vecs, &vec_seek, size);
|
ofs, &vecs, &vec_seek, size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1690,7 +1690,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
|
|||||||
len -= size;
|
len -= size;
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1776,7 +1776,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1786,7 +1786,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
|
|||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
UDELAY(map, chip, adr, 1000000/HZ);
|
UDELAY(map, chip, adr, 1000000/HZ);
|
||||||
}
|
}
|
||||||
@ -1849,7 +1849,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1870,7 +1870,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
|
|||||||
if (!ret) {
|
if (!ret) {
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_SYNCING;
|
chip->state = FL_SYNCING;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1884,7 +1884,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
|
|||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_SYNCING) {
|
if (chip->state == FL_SYNCING) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
chip->oldstate = FL_READY;
|
chip->oldstate = FL_READY;
|
||||||
@ -1941,7 +1941,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
|
|||||||
|
|
||||||
ENABLE_VPP(map);
|
ENABLE_VPP(map);
|
||||||
xip_disable(map, chip, adr);
|
xip_disable(map, chip, adr);
|
||||||
|
|
||||||
map_write(map, CMD(0x60), adr);
|
map_write(map, CMD(0x60), adr);
|
||||||
if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
|
if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
|
||||||
map_write(map, CMD(0x01), adr);
|
map_write(map, CMD(0x01), adr);
|
||||||
@ -1969,7 +1969,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1980,11 +1980,11 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
|
|||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
UDELAY(map, chip, adr, 1);
|
UDELAY(map, chip, adr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
chip->state = FL_STATUS;
|
chip->state = FL_STATUS;
|
||||||
xip_enable(map, chip, adr);
|
xip_enable(map, chip, adr);
|
||||||
@ -2004,9 +2004,9 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
ofs, len, 0);
|
ofs, len, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
|
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
|
||||||
ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
|
ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
|
||||||
|
|
||||||
#ifdef DEBUG_LOCK_BITS
|
#ifdef DEBUG_LOCK_BITS
|
||||||
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
|
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
|
||||||
__FUNCTION__, ret);
|
__FUNCTION__, ret);
|
||||||
@ -2030,20 +2030,20 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
|
|
||||||
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
|
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
|
||||||
ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
|
ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
|
||||||
|
|
||||||
#ifdef DEBUG_LOCK_BITS
|
#ifdef DEBUG_LOCK_BITS
|
||||||
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
|
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
|
||||||
__FUNCTION__, ret);
|
__FUNCTION__, ret);
|
||||||
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
|
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
|
||||||
ofs, len, 0);
|
ofs, len, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_OTP
|
#ifdef CONFIG_MTD_OTP
|
||||||
|
|
||||||
typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
|
typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
|
||||||
u_long data_offset, u_char *buf, u_int size,
|
u_long data_offset, u_char *buf, u_int size,
|
||||||
u_long prot_offset, u_int groupno, u_int groupsize);
|
u_long prot_offset, u_int groupno, u_int groupsize);
|
||||||
|
|
||||||
@ -2094,7 +2094,7 @@ do_otp_write(struct map_info *map, struct flchip *chip, u_long offset,
|
|||||||
|
|
||||||
datum = map_word_load_partial(map, datum, buf, gap, n);
|
datum = map_word_load_partial(map, datum, buf, gap, n);
|
||||||
ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
|
ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
offset += n;
|
offset += n;
|
||||||
@ -2287,7 +2287,7 @@ static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd,
|
|||||||
NULL, do_otp_lock, 1);
|
NULL, do_otp_lock, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd,
|
static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd,
|
||||||
struct otp_info *buf, size_t len)
|
struct otp_info *buf, size_t len)
|
||||||
{
|
{
|
||||||
size_t retlen;
|
size_t retlen;
|
||||||
@ -2330,7 +2330,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
|
|||||||
if (chip->oldstate == FL_READY) {
|
if (chip->oldstate == FL_READY) {
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_PM_SUSPENDED;
|
chip->state = FL_PM_SUSPENDED;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -2358,9 +2358,9 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
for (i--; i >=0; i--) {
|
for (i--; i >=0; i--) {
|
||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
/* No need to force it into a known state here,
|
/* No need to force it into a known state here,
|
||||||
because we're returning failure, and it didn't
|
because we're returning failure, and it didn't
|
||||||
@ -2371,8 +2371,8 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
|
|||||||
}
|
}
|
||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2384,11 +2384,11 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
|
|||||||
struct flchip *chip;
|
struct flchip *chip;
|
||||||
|
|
||||||
for (i=0; i<cfi->numchips; i++) {
|
for (i=0; i<cfi->numchips; i++) {
|
||||||
|
|
||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
/* Go to known state. Chip may have been power cycled */
|
/* Go to known state. Chip may have been power cycled */
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
map_write(map, CMD(0xFF), cfi->chips[i].start);
|
map_write(map, CMD(0xFF), cfi->chips[i].start);
|
||||||
@ -2410,7 +2410,7 @@ static int cfi_intelext_reset(struct mtd_info *mtd)
|
|||||||
struct flchip *chip = &cfi->chips[i];
|
struct flchip *chip = &cfi->chips[i];
|
||||||
|
|
||||||
/* force the completion of any ongoing operation
|
/* force the completion of any ongoing operation
|
||||||
and switch to array mode so any bootloader in
|
and switch to array mode so any bootloader in
|
||||||
flash is accessible for soft reboot. */
|
flash is accessible for soft reboot. */
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
ret = get_chip(map, chip, chip->start, FL_SYNCING);
|
ret = get_chip(map, chip, chip->start, FL_SYNCING);
|
||||||
|
@ -10,14 +10,14 @@
|
|||||||
*
|
*
|
||||||
* 4_by_16 work by Carolyn J. Smith
|
* 4_by_16 work by Carolyn J. Smith
|
||||||
*
|
*
|
||||||
* XIP support hooks by Vitaly Wool (based on code for Intel flash
|
* XIP support hooks by Vitaly Wool (based on code for Intel flash
|
||||||
* by Nicolas Pitre)
|
* by Nicolas Pitre)
|
||||||
*
|
*
|
||||||
* Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
|
* Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
|
||||||
*
|
*
|
||||||
* This code is GPL
|
* This code is GPL
|
||||||
*
|
*
|
||||||
* $Id: cfi_cmdset_0002.c,v 1.121 2005/11/07 09:00:01 gleixner Exp $
|
* $Id: cfi_cmdset_0002.c,v 1.122 2005/11/07 11:14:22 gleixner Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp)
|
|||||||
};
|
};
|
||||||
|
|
||||||
printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1);
|
printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1);
|
||||||
printk(" Address sensitive unlock: %s\n",
|
printk(" Address sensitive unlock: %s\n",
|
||||||
(extp->SiliconRevision & 1) ? "Not required" : "Required");
|
(extp->SiliconRevision & 1) ? "Not required" : "Required");
|
||||||
|
|
||||||
if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
|
if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
|
||||||
@ -118,9 +118,9 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp)
|
|||||||
else
|
else
|
||||||
printk(" Page mode: %d word page\n", extp->PageMode << 2);
|
printk(" Page mode: %d word page\n", extp->PageMode << 2);
|
||||||
|
|
||||||
printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VppMin >> 4, extp->VppMin & 0xf);
|
extp->VppMin >> 4, extp->VppMin & 0xf);
|
||||||
printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VppMax >> 4, extp->VppMax & 0xf);
|
extp->VppMax >> 4, extp->VppMax & 0xf);
|
||||||
|
|
||||||
if (extp->TopBottom < ARRAY_SIZE(top_bottom))
|
if (extp->TopBottom < ARRAY_SIZE(top_bottom))
|
||||||
@ -177,7 +177,7 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
|
|||||||
((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
|
((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
|
||||||
mtd->erase = cfi_amdstd_erase_chip;
|
mtd->erase = cfi_amdstd_erase_chip;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cfi_fixup cfi_fixup_table[] = {
|
static struct cfi_fixup cfi_fixup_table[] = {
|
||||||
@ -239,7 +239,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
|
|
||||||
if (cfi->cfi_mode==CFI_MODE_CFI){
|
if (cfi->cfi_mode==CFI_MODE_CFI){
|
||||||
unsigned char bootloc;
|
unsigned char bootloc;
|
||||||
/*
|
/*
|
||||||
* It's a real CFI chip, not one for which the probe
|
* It's a real CFI chip, not one for which the probe
|
||||||
* routine faked a CFI structure. So we read the feature
|
* routine faked a CFI structure. So we read the feature
|
||||||
* table from it.
|
* table from it.
|
||||||
@ -264,7 +264,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Install our own private info structure */
|
/* Install our own private info structure */
|
||||||
cfi->cmdset_priv = extp;
|
cfi->cmdset_priv = extp;
|
||||||
|
|
||||||
/* Apply cfi device specific fixups */
|
/* Apply cfi device specific fixups */
|
||||||
cfi_fixup(mtd, cfi_fixup_table);
|
cfi_fixup(mtd, cfi_fixup_table);
|
||||||
@ -272,7 +272,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
#ifdef DEBUG_CFI_FEATURES
|
#ifdef DEBUG_CFI_FEATURES
|
||||||
/* Tell the user about it in lots of lovely detail */
|
/* Tell the user about it in lots of lovely detail */
|
||||||
cfi_tell_features(extp);
|
cfi_tell_features(extp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bootloc = extp->TopBottom;
|
bootloc = extp->TopBottom;
|
||||||
if ((bootloc != 2) && (bootloc != 3)) {
|
if ((bootloc != 2) && (bootloc != 3)) {
|
||||||
@ -283,11 +283,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
|
|
||||||
if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
|
if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
|
||||||
printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
|
printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
|
||||||
|
|
||||||
for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
|
for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
|
||||||
int j = (cfi->cfiq->NumEraseRegions-1)-i;
|
int j = (cfi->cfiq->NumEraseRegions-1)-i;
|
||||||
__u32 swap;
|
__u32 swap;
|
||||||
|
|
||||||
swap = cfi->cfiq->EraseRegionInfo[i];
|
swap = cfi->cfiq->EraseRegionInfo[i];
|
||||||
cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
|
cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
|
||||||
cfi->cfiq->EraseRegionInfo[j] = swap;
|
cfi->cfiq->EraseRegionInfo[j] = swap;
|
||||||
@ -298,11 +298,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
cfi->addr_unlock2 = 0x2aa;
|
cfi->addr_unlock2 = 0x2aa;
|
||||||
/* Modify the unlock address if we are in compatibility mode */
|
/* Modify the unlock address if we are in compatibility mode */
|
||||||
if ( /* x16 in x8 mode */
|
if ( /* x16 in x8 mode */
|
||||||
((cfi->device_type == CFI_DEVICETYPE_X8) &&
|
((cfi->device_type == CFI_DEVICETYPE_X8) &&
|
||||||
(cfi->cfiq->InterfaceDesc == 2)) ||
|
(cfi->cfiq->InterfaceDesc == 2)) ||
|
||||||
/* x32 in x16 mode */
|
/* x32 in x16 mode */
|
||||||
((cfi->device_type == CFI_DEVICETYPE_X16) &&
|
((cfi->device_type == CFI_DEVICETYPE_X16) &&
|
||||||
(cfi->cfiq->InterfaceDesc == 4)))
|
(cfi->cfiq->InterfaceDesc == 4)))
|
||||||
{
|
{
|
||||||
cfi->addr_unlock1 = 0xaaa;
|
cfi->addr_unlock1 = 0xaaa;
|
||||||
cfi->addr_unlock2 = 0x555;
|
cfi->addr_unlock2 = 0x555;
|
||||||
@ -320,10 +320,10 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
|
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
|
||||||
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
|
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
|
||||||
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
|
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->fldrv = &cfi_amdstd_chipdrv;
|
map->fldrv = &cfi_amdstd_chipdrv;
|
||||||
|
|
||||||
return cfi_amdstd_setup(mtd);
|
return cfi_amdstd_setup(mtd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,24 +336,24 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
|
|||||||
unsigned long offset = 0;
|
unsigned long offset = 0;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
printk(KERN_NOTICE "number of %s chips: %d\n",
|
printk(KERN_NOTICE "number of %s chips: %d\n",
|
||||||
(cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
|
(cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
|
||||||
/* Select the correct geometry setup */
|
/* Select the correct geometry setup */
|
||||||
mtd->size = devsize * cfi->numchips;
|
mtd->size = devsize * cfi->numchips;
|
||||||
|
|
||||||
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
||||||
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
||||||
* mtd->numeraseregions, GFP_KERNEL);
|
* mtd->numeraseregions, GFP_KERNEL);
|
||||||
if (!mtd->eraseregions) {
|
if (!mtd->eraseregions) {
|
||||||
printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
|
printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n");
|
||||||
goto setup_err;
|
goto setup_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
||||||
unsigned long ernum, ersize;
|
unsigned long ernum, ersize;
|
||||||
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
||||||
ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
|
ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
|
||||||
|
|
||||||
if (mtd->erasesize < ersize) {
|
if (mtd->erasesize < ersize) {
|
||||||
mtd->erasesize = ersize;
|
mtd->erasesize = ersize;
|
||||||
}
|
}
|
||||||
@ -440,7 +440,7 @@ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word
|
|||||||
oldd = map_read(map, addr);
|
oldd = map_read(map, addr);
|
||||||
curd = map_read(map, addr);
|
curd = map_read(map, addr);
|
||||||
|
|
||||||
return map_word_equal(map, oldd, curd) &&
|
return map_word_equal(map, oldd, curd) &&
|
||||||
map_word_equal(map, curd, expected);
|
map_word_equal(map, curd, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,7 +472,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||||||
/* Someone else might have been playing with it. */
|
/* Someone else might have been playing with it. */
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FL_READY:
|
case FL_READY:
|
||||||
case FL_CFI_QUERY:
|
case FL_CFI_QUERY:
|
||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
@ -515,7 +515,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||||||
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
|
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
@ -618,7 +618,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
|
|||||||
* When a delay is required for the flash operation to complete, the
|
* When a delay is required for the flash operation to complete, the
|
||||||
* xip_udelay() function is polling for both the given timeout and pending
|
* xip_udelay() function is polling for both the given timeout and pending
|
||||||
* (but still masked) hardware interrupts. Whenever there is an interrupt
|
* (but still masked) hardware interrupts. Whenever there is an interrupt
|
||||||
* pending then the flash erase operation is suspended, array mode restored
|
* pending then the flash erase operation is suspended, array mode restored
|
||||||
* and interrupts unmasked. Task scheduling might also happen at that
|
* and interrupts unmasked. Task scheduling might also happen at that
|
||||||
* point. The CPU eventually returns from the interrupt or the call to
|
* point. The CPU eventually returns from the interrupt or the call to
|
||||||
* schedule() and the suspended flash operation is resumed for the remaining
|
* schedule() and the suspended flash operation is resumed for the remaining
|
||||||
@ -642,9 +642,9 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
|
|||||||
((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&
|
((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) &&
|
||||||
(cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
|
(cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) {
|
||||||
/*
|
/*
|
||||||
* Let's suspend the erase operation when supported.
|
* Let's suspend the erase operation when supported.
|
||||||
* Note that we currently don't try to suspend
|
* Note that we currently don't try to suspend
|
||||||
* interleaved chips if there is already another
|
* interleaved chips if there is already another
|
||||||
* operation suspended (imagine what happens
|
* operation suspended (imagine what happens
|
||||||
* when one chip was already done with the current
|
* when one chip was already done with the current
|
||||||
* operation while another chip suspended it, then
|
* operation while another chip suspended it, then
|
||||||
@ -780,8 +780,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
/* Ensure cmd read/writes are aligned. */
|
/* Ensure cmd read/writes are aligned. */
|
||||||
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
ret = get_chip(map, chip, cmd_addr, FL_READY);
|
ret = get_chip(map, chip, cmd_addr, FL_READY);
|
||||||
@ -861,7 +861,7 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
|
|||||||
#endif
|
#endif
|
||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
@ -873,7 +873,7 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
|
|||||||
timeo = jiffies + HZ;
|
timeo = jiffies + HZ;
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
@ -882,14 +882,14 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
|
|||||||
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
|
|
||||||
map_copy_from(map, buf, adr, len);
|
map_copy_from(map, buf, adr, len);
|
||||||
|
|
||||||
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
|
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
|
|
||||||
@ -998,7 +998,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
|||||||
chip->word_write_time);
|
chip->word_write_time);
|
||||||
|
|
||||||
/* See comment above for timeout value. */
|
/* See comment above for timeout value. */
|
||||||
timeo = jiffies + uWriteTimeout;
|
timeo = jiffies + uWriteTimeout;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (chip->state != FL_WRITING) {
|
if (chip->state != FL_WRITING) {
|
||||||
/* Someone's suspended the write. Sleep */
|
/* Someone's suspended the write. Sleep */
|
||||||
@ -1033,7 +1033,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
|||||||
map_write( map, CMD(0xF0), chip->start );
|
map_write( map, CMD(0xF0), chip->start );
|
||||||
/* FIXME - should have reset delay before continuing */
|
/* FIXME - should have reset delay before continuing */
|
||||||
|
|
||||||
if (++retry_cnt <= MAX_WORD_RETRIES)
|
if (++retry_cnt <= MAX_WORD_RETRIES)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@ -1101,27 +1101,27 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
|
|
||||||
/* Number of bytes to copy from buffer */
|
/* Number of bytes to copy from buffer */
|
||||||
n = min_t(int, len, map_bankwidth(map)-i);
|
n = min_t(int, len, map_bankwidth(map)-i);
|
||||||
|
|
||||||
tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
|
tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
|
||||||
|
|
||||||
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
||||||
bus_ofs, tmp_buf);
|
bus_ofs, tmp_buf);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ofs += n;
|
ofs += n;
|
||||||
buf += n;
|
buf += n;
|
||||||
(*retlen) += n;
|
(*retlen) += n;
|
||||||
len -= n;
|
len -= n;
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are now aligned, write as much as possible */
|
/* We are now aligned, write as much as possible */
|
||||||
while(len >= map_bankwidth(map)) {
|
while(len >= map_bankwidth(map)) {
|
||||||
map_word datum;
|
map_word datum;
|
||||||
@ -1139,7 +1139,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
len -= map_bankwidth(map);
|
len -= map_bankwidth(map);
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1177,12 +1177,12 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
spin_unlock(cfi->chips[chipnum].mutex);
|
spin_unlock(cfi->chips[chipnum].mutex);
|
||||||
|
|
||||||
tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
|
tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
|
||||||
|
|
||||||
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
ret = do_write_oneword(map, &cfi->chips[chipnum],
|
||||||
ofs, tmp_buf);
|
ofs, tmp_buf);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
(*retlen) += len;
|
(*retlen) += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1194,7 +1194,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
* FIXME: interleaved mode not tested, and probably not supported!
|
* FIXME: interleaved mode not tested, and probably not supported!
|
||||||
*/
|
*/
|
||||||
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||||
unsigned long adr, const u_char *buf,
|
unsigned long adr, const u_char *buf,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
@ -1224,7 +1224,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
XIP_INVAL_CACHED_RANGE(map, adr, len);
|
XIP_INVAL_CACHED_RANGE(map, adr, len);
|
||||||
ENABLE_VPP(map);
|
ENABLE_VPP(map);
|
||||||
xip_disable(map, chip, cmd_adr);
|
xip_disable(map, chip, cmd_adr);
|
||||||
|
|
||||||
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
//cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
//cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
|
||||||
@ -1258,8 +1258,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
adr, map_bankwidth(map),
|
adr, map_bankwidth(map),
|
||||||
chip->word_write_time);
|
chip->word_write_time);
|
||||||
|
|
||||||
timeo = jiffies + uWriteTimeout;
|
timeo = jiffies + uWriteTimeout;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (chip->state != FL_WRITING) {
|
if (chip->state != FL_WRITING) {
|
||||||
/* Someone's suspended the write. Sleep */
|
/* Someone's suspended the write. Sleep */
|
||||||
@ -1353,7 +1353,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
if (size % map_bankwidth(map))
|
if (size % map_bankwidth(map))
|
||||||
size -= size % map_bankwidth(map);
|
size -= size % map_bankwidth(map);
|
||||||
|
|
||||||
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
||||||
ofs, buf, size);
|
ofs, buf, size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1364,7 +1364,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
len -= size;
|
len -= size;
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1581,7 +1581,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1604,7 +1604,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1631,7 +1631,7 @@ static void cfi_amdstd_sync (struct mtd_info *mtd)
|
|||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_SYNCING;
|
chip->state = FL_SYNCING;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1642,13 +1642,13 @@ static void cfi_amdstd_sync (struct mtd_info *mtd)
|
|||||||
default:
|
default:
|
||||||
/* Not an idle state */
|
/* Not an idle state */
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
|
|
||||||
remove_wait_queue(&chip->wq, &wait);
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1659,7 +1659,7 @@ static void cfi_amdstd_sync (struct mtd_info *mtd)
|
|||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_SYNCING) {
|
if (chip->state == FL_SYNCING) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
@ -1689,7 +1689,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd)
|
|||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_PM_SUSPENDED;
|
chip->state = FL_PM_SUSPENDED;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1710,7 +1710,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd)
|
|||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
@ -1718,7 +1718,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd)
|
|||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1731,11 +1731,11 @@ static void cfi_amdstd_resume(struct mtd_info *mtd)
|
|||||||
struct flchip *chip;
|
struct flchip *chip;
|
||||||
|
|
||||||
for (i=0; i<cfi->numchips; i++) {
|
for (i=0; i<cfi->numchips; i++) {
|
||||||
|
|
||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock(chip->mutex);
|
spin_lock(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
chip->state = FL_READY;
|
chip->state = FL_READY;
|
||||||
map_write(map, CMD(0xF0), chip->start);
|
map_write(map, CMD(0xF0), chip->start);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* (C) 2000 Red Hat. GPL'd
|
* (C) 2000 Red Hat. GPL'd
|
||||||
*
|
*
|
||||||
* $Id: cfi_cmdset_0020.c,v 1.20 2005/07/20 21:01:14 tpoynor Exp $
|
* $Id: cfi_cmdset_0020.c,v 1.22 2005/11/07 11:14:22 gleixner Exp $
|
||||||
*
|
*
|
||||||
* 10/10/2000 Nicolas Pitre <nico@cam.org>
|
* 10/10/2000 Nicolas Pitre <nico@cam.org>
|
||||||
* - completely revamped method functions so they are aware and
|
* - completely revamped method functions so they are aware and
|
||||||
@ -81,17 +81,17 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||||||
printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
|
printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
|
||||||
printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
|
printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
|
||||||
for (i=9; i<32; i++) {
|
for (i=9; i<32; i++) {
|
||||||
if (extp->FeatureSupport & (1<<i))
|
if (extp->FeatureSupport & (1<<i))
|
||||||
printk(" - Unknown Bit %X: supported\n", i);
|
printk(" - Unknown Bit %X: supported\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
|
printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
|
||||||
printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
|
printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
|
||||||
for (i=1; i<8; i++) {
|
for (i=1; i<8; i++) {
|
||||||
if (extp->SuspendCmdSupport & (1<<i))
|
if (extp->SuspendCmdSupport & (1<<i))
|
||||||
printk(" - Unknown Bit %X: supported\n", i);
|
printk(" - Unknown Bit %X: supported\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
|
printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
|
||||||
printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
|
printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
|
||||||
printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
|
printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
|
||||||
@ -99,11 +99,11 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||||||
if (extp->BlkStatusRegMask & (1<<i))
|
if (extp->BlkStatusRegMask & (1<<i))
|
||||||
printk(" - Unknown Bit %X Active: yes\n",i);
|
printk(" - Unknown Bit %X Active: yes\n",i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VccOptimal >> 8, extp->VccOptimal & 0xf);
|
extp->VccOptimal >> 8, extp->VccOptimal & 0xf);
|
||||||
if (extp->VppOptimal)
|
if (extp->VppOptimal)
|
||||||
printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
|
||||||
extp->VppOptimal >> 8, extp->VppOptimal & 0xf);
|
extp->VppOptimal >> 8, extp->VppOptimal & 0xf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -121,7 +121,7 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (cfi->cfi_mode) {
|
if (cfi->cfi_mode) {
|
||||||
/*
|
/*
|
||||||
* It's a real CFI chip, not one for which the probe
|
* It's a real CFI chip, not one for which the probe
|
||||||
* routine faked a CFI structure. So we read the feature
|
* routine faked a CFI structure. So we read the feature
|
||||||
* table from it.
|
* table from it.
|
||||||
@ -145,21 +145,21 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
|
|||||||
/* Do some byteswapping if necessary */
|
/* Do some byteswapping if necessary */
|
||||||
extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport);
|
extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport);
|
||||||
extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask);
|
extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask);
|
||||||
|
|
||||||
#ifdef DEBUG_CFI_FEATURES
|
#ifdef DEBUG_CFI_FEATURES
|
||||||
/* Tell the user about it in lots of lovely detail */
|
/* Tell the user about it in lots of lovely detail */
|
||||||
cfi_tell_features(extp);
|
cfi_tell_features(extp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Install our own private info structure */
|
/* Install our own private info structure */
|
||||||
cfi->cmdset_priv = extp;
|
cfi->cmdset_priv = extp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i< cfi->numchips; i++) {
|
for (i=0; i< cfi->numchips; i++) {
|
||||||
cfi->chips[i].word_write_time = 128;
|
cfi->chips[i].word_write_time = 128;
|
||||||
cfi->chips[i].buffer_write_time = 128;
|
cfi->chips[i].buffer_write_time = 128;
|
||||||
cfi->chips[i].erase_time = 1024;
|
cfi->chips[i].erase_time = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfi_staa_setup(map);
|
return cfi_staa_setup(map);
|
||||||
}
|
}
|
||||||
@ -187,15 +187,15 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
|
|||||||
mtd->size = devsize * cfi->numchips;
|
mtd->size = devsize * cfi->numchips;
|
||||||
|
|
||||||
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
|
||||||
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
|
||||||
* mtd->numeraseregions, GFP_KERNEL);
|
* mtd->numeraseregions, GFP_KERNEL);
|
||||||
if (!mtd->eraseregions) {
|
if (!mtd->eraseregions) {
|
||||||
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
|
printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
|
||||||
kfree(cfi->cmdset_priv);
|
kfree(cfi->cmdset_priv);
|
||||||
kfree(mtd);
|
kfree(mtd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
||||||
unsigned long ernum, ersize;
|
unsigned long ernum, ersize;
|
||||||
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
|
||||||
@ -228,7 +228,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
|
|||||||
mtd->eraseregions[i].numblocks);
|
mtd->eraseregions[i].numblocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also select the correct geometry setup too */
|
/* Also select the correct geometry setup too */
|
||||||
mtd->erase = cfi_staa_erase_varsize;
|
mtd->erase = cfi_staa_erase_varsize;
|
||||||
mtd->read = cfi_staa_read;
|
mtd->read = cfi_staa_read;
|
||||||
mtd->write = cfi_staa_write_buffers;
|
mtd->write = cfi_staa_write_buffers;
|
||||||
@ -259,8 +259,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
|
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
|
||||||
/* Ensure cmd read/writes are aligned. */
|
/* Ensure cmd read/writes are aligned. */
|
||||||
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
cmd_addr = adr & ~(map_bankwidth(map)-1);
|
||||||
|
|
||||||
/* Let's determine this according to the interleave only once */
|
/* Let's determine this according to the interleave only once */
|
||||||
status_OK = CMD(0x80);
|
status_OK = CMD(0x80);
|
||||||
@ -276,7 +276,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
case FL_ERASING:
|
case FL_ERASING:
|
||||||
if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2))
|
if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2))
|
||||||
goto sleep; /* We don't support erase suspend */
|
goto sleep; /* We don't support erase suspend */
|
||||||
|
|
||||||
map_write (map, CMD(0xb0), cmd_addr);
|
map_write (map, CMD(0xb0), cmd_addr);
|
||||||
/* If the flash has finished erasing, then 'erase suspend'
|
/* If the flash has finished erasing, then 'erase suspend'
|
||||||
* appears to make some (28F320) flash devices switch to
|
* appears to make some (28F320) flash devices switch to
|
||||||
@ -291,7 +291,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
status = map_read(map, cmd_addr);
|
status = map_read(map, cmd_addr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
/* Urgh */
|
/* Urgh */
|
||||||
map_write(map, CMD(0xd0), cmd_addr);
|
map_write(map, CMD(0xd0), cmd_addr);
|
||||||
@ -303,17 +303,17 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
"suspended: status = 0x%lx\n", status.x[0]);
|
"suspended: status = 0x%lx\n", status.x[0]);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
suspended = 1;
|
suspended = 1;
|
||||||
map_write(map, CMD(0xff), cmd_addr);
|
map_write(map, CMD(0xff), cmd_addr);
|
||||||
chip->state = FL_READY;
|
chip->state = FL_READY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
case FL_WRITING:
|
case FL_WRITING:
|
||||||
/* Not quite yet */
|
/* Not quite yet */
|
||||||
@ -334,7 +334,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
chip->state = FL_READY;
|
chip->state = FL_READY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Urgh. Chip not yet ready to talk to us. */
|
/* Urgh. Chip not yet ready to talk to us. */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
@ -364,17 +364,17 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
|||||||
|
|
||||||
if (suspended) {
|
if (suspended) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
/* What if one interleaved chip has finished and the
|
/* What if one interleaved chip has finished and the
|
||||||
other hasn't? The old code would leave the finished
|
other hasn't? The old code would leave the finished
|
||||||
one in READY mode. That's bad, and caused -EROFS
|
one in READY mode. That's bad, and caused -EROFS
|
||||||
errors to be returned from do_erase_oneblock because
|
errors to be returned from do_erase_oneblock because
|
||||||
that's the only bit it checked for at the time.
|
that's the only bit it checked for at the time.
|
||||||
As the state machine appears to explicitly allow
|
As the state machine appears to explicitly allow
|
||||||
sending the 0x70 (Read Status) command to an erasing
|
sending the 0x70 (Read Status) command to an erasing
|
||||||
chip and expecting it to be ignored, that's what we
|
chip and expecting it to be ignored, that's what we
|
||||||
do. */
|
do. */
|
||||||
map_write(map, CMD(0xd0), cmd_addr);
|
map_write(map, CMD(0xd0), cmd_addr);
|
||||||
map_write(map, CMD(0x70), cmd_addr);
|
map_write(map, CMD(0x70), cmd_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
@ -414,14 +414,14 @@ static int cfi_staa_read (struct mtd_info *mtd, loff_t from, size_t len, size_t
|
|||||||
*retlen += thislen;
|
*retlen += thislen;
|
||||||
len -= thislen;
|
len -= thislen;
|
||||||
buf += thislen;
|
buf += thislen;
|
||||||
|
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||||
unsigned long adr, const u_char *buf, int len)
|
unsigned long adr, const u_char *buf, int len)
|
||||||
{
|
{
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
@ -429,7 +429,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
unsigned long cmd_adr, timeo;
|
unsigned long cmd_adr, timeo;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
int wbufsize, z;
|
int wbufsize, z;
|
||||||
|
|
||||||
/* M58LW064A requires bus alignment for buffer wriets -- saw */
|
/* M58LW064A requires bus alignment for buffer wriets -- saw */
|
||||||
if (adr & (map_bankwidth(map)-1))
|
if (adr & (map_bankwidth(map)-1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -437,10 +437,10 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
|
wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
cmd_adr = adr & ~(wbufsize-1);
|
cmd_adr = adr & ~(wbufsize-1);
|
||||||
|
|
||||||
/* Let's determine this according to the interleave only once */
|
/* Let's determine this according to the interleave only once */
|
||||||
status_OK = CMD(0x80);
|
status_OK = CMD(0x80);
|
||||||
|
|
||||||
timeo = jiffies + HZ;
|
timeo = jiffies + HZ;
|
||||||
retry:
|
retry:
|
||||||
|
|
||||||
@ -448,7 +448,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
|
printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
|
||||||
#endif
|
#endif
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
/* Check that the chip's ready to talk to us.
|
/* Check that the chip's ready to talk to us.
|
||||||
* Later, we can actually think about interrupting it
|
* Later, we can actually think about interrupting it
|
||||||
* if it's in FL_ERASING state.
|
* if it's in FL_ERASING state.
|
||||||
@ -457,7 +457,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
switch (chip->state) {
|
switch (chip->state) {
|
||||||
case FL_READY:
|
case FL_READY:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FL_CFI_QUERY:
|
case FL_CFI_QUERY:
|
||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
map_write(map, CMD(0x70), cmd_adr);
|
map_write(map, CMD(0x70), cmd_adr);
|
||||||
@ -522,7 +522,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
|
|
||||||
/* Write length of data to come */
|
/* Write length of data to come */
|
||||||
map_write(map, CMD(len/map_bankwidth(map)-1), cmd_adr );
|
map_write(map, CMD(len/map_bankwidth(map)-1), cmd_adr );
|
||||||
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
for (z = 0; z < len;
|
for (z = 0; z < len;
|
||||||
z += map_bankwidth(map), buf += map_bankwidth(map)) {
|
z += map_bankwidth(map), buf += map_bankwidth(map)) {
|
||||||
@ -569,7 +569,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");
|
printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
@ -581,9 +581,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
if (!chip->buffer_write_time)
|
if (!chip->buffer_write_time)
|
||||||
chip->buffer_write_time++;
|
chip->buffer_write_time++;
|
||||||
}
|
}
|
||||||
if (z > 1)
|
if (z > 1)
|
||||||
chip->buffer_write_time++;
|
chip->buffer_write_time++;
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
DISABLE_VPP(map);
|
DISABLE_VPP(map);
|
||||||
chip->state = FL_STATUS;
|
chip->state = FL_STATUS;
|
||||||
@ -607,7 +607,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
|
static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
|
||||||
size_t len, size_t *retlen, const u_char *buf)
|
size_t len, size_t *retlen, const u_char *buf)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
@ -629,7 +629,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
|
|||||||
printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
|
printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
|
||||||
printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
|
printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Write buffer is worth it only if more than one word to write... */
|
/* Write buffer is worth it only if more than one word to write... */
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
/* We must not cross write block boundaries */
|
/* We must not cross write block boundaries */
|
||||||
@ -638,7 +638,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
|
|||||||
if (size > len)
|
if (size > len)
|
||||||
size = len;
|
size = len;
|
||||||
|
|
||||||
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
ret = do_write_buffer(map, &cfi->chips[chipnum],
|
||||||
ofs, buf, size);
|
ofs, buf, size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -649,13 +649,13 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
|
|||||||
len -= size;
|
len -= size;
|
||||||
|
|
||||||
if (ofs >> cfi->chipshift) {
|
if (ofs >> cfi->chipshift) {
|
||||||
chipnum ++;
|
chipnum ++;
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
if (chipnum == cfi->numchips)
|
if (chipnum == cfi->numchips)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,7 +765,7 @@ retry:
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Urgh. Chip not yet ready to talk to us. */
|
/* Urgh. Chip not yet ready to talk to us. */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
@ -798,7 +798,7 @@ retry:
|
|||||||
map_write(map, CMD(0x20), adr);
|
map_write(map, CMD(0x20), adr);
|
||||||
map_write(map, CMD(0xD0), adr);
|
map_write(map, CMD(0xD0), adr);
|
||||||
chip->state = FL_ERASING;
|
chip->state = FL_ERASING;
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
@ -823,7 +823,7 @@ retry:
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -833,13 +833,13 @@ retry:
|
|||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
DISABLE_VPP(map);
|
DISABLE_VPP(map);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -864,7 +864,7 @@ retry:
|
|||||||
/* Reset the error bits */
|
/* Reset the error bits */
|
||||||
map_write(map, CMD(0x50), adr);
|
map_write(map, CMD(0x50), adr);
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
|
|
||||||
if ((chipstatus & 0x30) == 0x30) {
|
if ((chipstatus & 0x30) == 0x30) {
|
||||||
printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
|
printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@ -913,17 +913,17 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
/* Skip all erase regions which are ended before the start of
|
/* Skip all erase regions which are ended before the start of
|
||||||
the requested erase. Actually, to save on the calculations,
|
the requested erase. Actually, to save on the calculations,
|
||||||
we skip to the first erase region which starts after the
|
we skip to the first erase region which starts after the
|
||||||
start of the requested erase, and then go back one.
|
start of the requested erase, and then go back one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
|
while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
|
||||||
i++;
|
i++;
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
/* OK, now i is pointing at the erase region in which this
|
/* OK, now i is pointing at the erase region in which this
|
||||||
erase request starts. Check the start of the requested
|
erase request starts. Check the start of the requested
|
||||||
erase range is aligned with the erase size which is in
|
erase range is aligned with the erase size which is in
|
||||||
effect here.
|
effect here.
|
||||||
@ -946,7 +946,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
the address actually falls
|
the address actually falls
|
||||||
*/
|
*/
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
if ((instr->addr + instr->len) & (regions[i].erasesize-1))
|
if ((instr->addr + instr->len) & (regions[i].erasesize-1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -958,7 +958,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
|
|
||||||
while(len) {
|
while(len) {
|
||||||
ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
|
ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -971,15 +971,15 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
if (adr >> cfi->chipshift) {
|
if (adr >> cfi->chipshift) {
|
||||||
adr = 0;
|
adr = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
|
|
||||||
if (chipnum >= cfi->numchips)
|
if (chipnum >= cfi->numchips)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,7 +1005,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
|
|||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_SYNCING;
|
chip->state = FL_SYNCING;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1016,11 +1016,11 @@ static void cfi_staa_sync (struct mtd_info *mtd)
|
|||||||
default:
|
default:
|
||||||
/* Not an idle state */
|
/* Not an idle state */
|
||||||
add_wait_queue(&chip->wq, &wait);
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
schedule();
|
schedule();
|
||||||
remove_wait_queue(&chip->wq, &wait);
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1031,7 +1031,7 @@ static void cfi_staa_sync (struct mtd_info *mtd)
|
|||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_SYNCING) {
|
if (chip->state == FL_SYNCING) {
|
||||||
chip->state = chip->oldstate;
|
chip->state = chip->oldstate;
|
||||||
wake_up(&chip->wq);
|
wake_up(&chip->wq);
|
||||||
@ -1066,9 +1066,9 @@ retry:
|
|||||||
|
|
||||||
case FL_STATUS:
|
case FL_STATUS:
|
||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Urgh. Chip not yet ready to talk to us. */
|
/* Urgh. Chip not yet ready to talk to us. */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
@ -1097,7 +1097,7 @@ retry:
|
|||||||
map_write(map, CMD(0x60), adr);
|
map_write(map, CMD(0x60), adr);
|
||||||
map_write(map, CMD(0x01), adr);
|
map_write(map, CMD(0x01), adr);
|
||||||
chip->state = FL_LOCKING;
|
chip->state = FL_LOCKING;
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
@ -1111,7 +1111,7 @@ retry:
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1121,13 +1121,13 @@ retry:
|
|||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the lock, wait a while and retry */
|
/* Latency issues. Drop the lock, wait a while and retry */
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
chip->state = FL_STATUS;
|
chip->state = FL_STATUS;
|
||||||
DISABLE_VPP(map);
|
DISABLE_VPP(map);
|
||||||
@ -1171,8 +1171,8 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
||||||
printk("after lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
|
printk("after lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
|
||||||
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1182,7 +1182,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
if (adr >> cfi->chipshift) {
|
if (adr >> cfi->chipshift) {
|
||||||
adr = 0;
|
adr = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
|
|
||||||
if (chipnum >= cfi->numchips)
|
if (chipnum >= cfi->numchips)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1217,7 +1217,7 @@ retry:
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Urgh. Chip not yet ready to talk to us. */
|
/* Urgh. Chip not yet ready to talk to us. */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
@ -1246,7 +1246,7 @@ retry:
|
|||||||
map_write(map, CMD(0x60), adr);
|
map_write(map, CMD(0x60), adr);
|
||||||
map_write(map, CMD(0xD0), adr);
|
map_write(map, CMD(0xD0), adr);
|
||||||
chip->state = FL_UNLOCKING;
|
chip->state = FL_UNLOCKING;
|
||||||
|
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
@ -1260,7 +1260,7 @@ retry:
|
|||||||
status = map_read(map, adr);
|
status = map_read(map, adr);
|
||||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* OK Still waiting */
|
/* OK Still waiting */
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
map_write(map, CMD(0x70), adr);
|
map_write(map, CMD(0x70), adr);
|
||||||
@ -1270,13 +1270,13 @@ retry:
|
|||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latency issues. Drop the unlock, wait a while and retry */
|
/* Latency issues. Drop the unlock, wait a while and retry */
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
cfi_udelay(1);
|
cfi_udelay(1);
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done and happy. */
|
/* Done and happy. */
|
||||||
chip->state = FL_STATUS;
|
chip->state = FL_STATUS;
|
||||||
DISABLE_VPP(map);
|
DISABLE_VPP(map);
|
||||||
@ -1301,7 +1301,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
{
|
{
|
||||||
unsigned long temp_adr = adr;
|
unsigned long temp_adr = adr;
|
||||||
unsigned long temp_len = len;
|
unsigned long temp_len = len;
|
||||||
|
|
||||||
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
||||||
while (temp_len) {
|
while (temp_len) {
|
||||||
printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor)));
|
printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor)));
|
||||||
@ -1319,7 +1319,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
|
printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
|
||||||
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1343,7 +1343,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
|
|||||||
case FL_JEDEC_QUERY:
|
case FL_JEDEC_QUERY:
|
||||||
chip->oldstate = chip->state;
|
chip->oldstate = chip->state;
|
||||||
chip->state = FL_PM_SUSPENDED;
|
chip->state = FL_PM_SUSPENDED;
|
||||||
/* No need to wake_up() on this state change -
|
/* No need to wake_up() on this state change -
|
||||||
* as the whole point is that nobody can do anything
|
* as the whole point is that nobody can do anything
|
||||||
* with the chip now anyway.
|
* with the chip now anyway.
|
||||||
*/
|
*/
|
||||||
@ -1362,9 +1362,9 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
for (i--; i >=0; i--) {
|
for (i--; i >=0; i--) {
|
||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
/* No need to force it into a known state here,
|
/* No need to force it into a known state here,
|
||||||
because we're returning failure, and it didn't
|
because we're returning failure, and it didn't
|
||||||
@ -1374,8 +1374,8 @@ static int cfi_staa_suspend(struct mtd_info *mtd)
|
|||||||
}
|
}
|
||||||
spin_unlock_bh(chip->mutex);
|
spin_unlock_bh(chip->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1387,11 +1387,11 @@ static void cfi_staa_resume(struct mtd_info *mtd)
|
|||||||
struct flchip *chip;
|
struct flchip *chip;
|
||||||
|
|
||||||
for (i=0; i<cfi->numchips; i++) {
|
for (i=0; i<cfi->numchips; i++) {
|
||||||
|
|
||||||
chip = &cfi->chips[i];
|
chip = &cfi->chips[i];
|
||||||
|
|
||||||
spin_lock_bh(chip->mutex);
|
spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
/* Go to known state. Chip may have been power cycled */
|
/* Go to known state. Chip may have been power cycled */
|
||||||
if (chip->state == FL_PM_SUSPENDED) {
|
if (chip->state == FL_PM_SUSPENDED) {
|
||||||
map_write(map, CMD(0xFF), 0);
|
map_write(map, CMD(0xFF), 0);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Common Flash Interface probe code.
|
Common Flash Interface probe code.
|
||||||
(C) 2000 Red Hat. GPL'd.
|
(C) 2000 Red Hat. GPL'd.
|
||||||
$Id: cfi_probe.c,v 1.83 2004/11/16 18:19:02 nico Exp $
|
$Id: cfi_probe.c,v 1.84 2005/11/07 11:14:23 gleixner Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
#include <linux/mtd/cfi.h>
|
#include <linux/mtd/cfi.h>
|
||||||
#include <linux/mtd/gen_probe.h>
|
#include <linux/mtd/gen_probe.h>
|
||||||
|
|
||||||
//#define DEBUG_CFI
|
//#define DEBUG_CFI
|
||||||
|
|
||||||
#ifdef DEBUG_CFI
|
#ifdef DEBUG_CFI
|
||||||
static void print_cfi_ident(struct cfi_ident *);
|
static void print_cfi_ident(struct cfi_ident *);
|
||||||
@ -103,7 +103,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
unsigned long *chip_map, struct cfi_private *cfi)
|
unsigned long *chip_map, struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((base + 0) >= map->size) {
|
if ((base + 0) >= map->size) {
|
||||||
printk(KERN_NOTICE
|
printk(KERN_NOTICE
|
||||||
"Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
|
"Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
|
||||||
@ -128,7 +128,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cfi->numchips) {
|
if (!cfi->numchips) {
|
||||||
/* This is the first time we're called. Set up the CFI
|
/* This is the first time we're called. Set up the CFI
|
||||||
stuff accordingly and return */
|
stuff accordingly and return */
|
||||||
return cfi_chip_setup(map, cfi);
|
return cfi_chip_setup(map, cfi);
|
||||||
}
|
}
|
||||||
@ -138,13 +138,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
unsigned long start;
|
unsigned long start;
|
||||||
if(!test_bit(i, chip_map)) {
|
if(!test_bit(i, chip_map)) {
|
||||||
/* Skip location; no valid chip at this address */
|
/* Skip location; no valid chip at this address */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
start = i << cfi->chipshift;
|
start = i << cfi->chipshift;
|
||||||
/* This chip should be in read mode if it's one
|
/* This chip should be in read mode if it's one
|
||||||
we've already touched. */
|
we've already touched. */
|
||||||
if (qry_present(map, start, cfi)) {
|
if (qry_present(map, start, cfi)) {
|
||||||
/* Eep. This chip also had the QRY marker.
|
/* Eep. This chip also had the QRY marker.
|
||||||
* Is it an alias for the new one? */
|
* Is it an alias for the new one? */
|
||||||
cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
|
||||||
@ -156,13 +156,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
map->name, base, start);
|
map->name, base, start);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Yes, it's actually got QRY for data. Most
|
/* Yes, it's actually got QRY for data. Most
|
||||||
* unfortunate. Stick the new chip in read mode
|
* unfortunate. Stick the new chip in read mode
|
||||||
* too and if it's the same, assume it's an alias. */
|
* too and if it's the same, assume it's an alias. */
|
||||||
/* FIXME: Use other modes to do a proper check */
|
/* FIXME: Use other modes to do a proper check */
|
||||||
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
|
||||||
|
|
||||||
if (qry_present(map, base, cfi)) {
|
if (qry_present(map, base, cfi)) {
|
||||||
xip_allowed(base, map);
|
xip_allowed(base, map);
|
||||||
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
|
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
|
||||||
@ -171,12 +171,12 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK, if we got to here, then none of the previous chips appear to
|
/* OK, if we got to here, then none of the previous chips appear to
|
||||||
be aliases for the current one. */
|
be aliases for the current one. */
|
||||||
set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
|
set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
|
||||||
cfi->numchips++;
|
cfi->numchips++;
|
||||||
|
|
||||||
/* Put it back into Read Mode */
|
/* Put it back into Read Mode */
|
||||||
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
|
||||||
@ -185,11 +185,11 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
|
|||||||
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\n",
|
||||||
map->name, cfi->interleave, cfi->device_type*8, base,
|
map->name, cfi->interleave, cfi->device_type*8, base,
|
||||||
map->bankwidth*8);
|
map->bankwidth*8);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __xipram cfi_chip_setup(struct map_info *map,
|
static int __xipram cfi_chip_setup(struct map_info *map,
|
||||||
struct cfi_private *cfi)
|
struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
int ofs_factor = cfi->interleave*cfi->device_type;
|
int ofs_factor = cfi->interleave*cfi->device_type;
|
||||||
@ -209,11 +209,11 @@ static int __xipram cfi_chip_setup(struct map_info *map,
|
|||||||
printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
|
printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(cfi->cfiq,0,sizeof(struct cfi_ident));
|
memset(cfi->cfiq,0,sizeof(struct cfi_ident));
|
||||||
|
|
||||||
cfi->cfi_mode = CFI_MODE_CFI;
|
cfi->cfi_mode = CFI_MODE_CFI;
|
||||||
|
|
||||||
/* Read the CFI info structure */
|
/* Read the CFI info structure */
|
||||||
xip_disable_qry(base, map, cfi);
|
xip_disable_qry(base, map, cfi);
|
||||||
for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
|
for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
|
||||||
@ -231,7 +231,7 @@ static int __xipram cfi_chip_setup(struct map_info *map,
|
|||||||
cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
|
||||||
cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
|
||||||
cfi->mfr = cfi_read_query(map, base);
|
cfi->mfr = cfi_read_query(map, base);
|
||||||
cfi->id = cfi_read_query(map, base + ofs_factor);
|
cfi->id = cfi_read_query(map, base + ofs_factor);
|
||||||
|
|
||||||
/* Put it back into Read Mode */
|
/* Put it back into Read Mode */
|
||||||
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
|
||||||
@ -255,10 +255,10 @@ static int __xipram cfi_chip_setup(struct map_info *map,
|
|||||||
|
|
||||||
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
|
||||||
cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
|
cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
|
||||||
|
|
||||||
#ifdef DEBUG_CFI
|
#ifdef DEBUG_CFI
|
||||||
printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
|
printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
|
||||||
i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
|
i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
|
||||||
(cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
|
(cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -271,33 +271,33 @@ static int __xipram cfi_chip_setup(struct map_info *map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CFI
|
#ifdef DEBUG_CFI
|
||||||
static char *vendorname(__u16 vendor)
|
static char *vendorname(__u16 vendor)
|
||||||
{
|
{
|
||||||
switch (vendor) {
|
switch (vendor) {
|
||||||
case P_ID_NONE:
|
case P_ID_NONE:
|
||||||
return "None";
|
return "None";
|
||||||
|
|
||||||
case P_ID_INTEL_EXT:
|
case P_ID_INTEL_EXT:
|
||||||
return "Intel/Sharp Extended";
|
return "Intel/Sharp Extended";
|
||||||
|
|
||||||
case P_ID_AMD_STD:
|
case P_ID_AMD_STD:
|
||||||
return "AMD/Fujitsu Standard";
|
return "AMD/Fujitsu Standard";
|
||||||
|
|
||||||
case P_ID_INTEL_STD:
|
case P_ID_INTEL_STD:
|
||||||
return "Intel/Sharp Standard";
|
return "Intel/Sharp Standard";
|
||||||
|
|
||||||
case P_ID_AMD_EXT:
|
case P_ID_AMD_EXT:
|
||||||
return "AMD/Fujitsu Extended";
|
return "AMD/Fujitsu Extended";
|
||||||
|
|
||||||
case P_ID_WINBOND:
|
case P_ID_WINBOND:
|
||||||
return "Winbond Standard";
|
return "Winbond Standard";
|
||||||
|
|
||||||
case P_ID_ST_ADV:
|
case P_ID_ST_ADV:
|
||||||
return "ST Advanced";
|
return "ST Advanced";
|
||||||
|
|
||||||
case P_ID_MITSUBISHI_STD:
|
case P_ID_MITSUBISHI_STD:
|
||||||
return "Mitsubishi Standard";
|
return "Mitsubishi Standard";
|
||||||
|
|
||||||
case P_ID_MITSUBISHI_EXT:
|
case P_ID_MITSUBISHI_EXT:
|
||||||
return "Mitsubishi Extended";
|
return "Mitsubishi Extended";
|
||||||
|
|
||||||
@ -306,13 +306,13 @@ static char *vendorname(__u16 vendor)
|
|||||||
|
|
||||||
case P_ID_INTEL_PERFORMANCE:
|
case P_ID_INTEL_PERFORMANCE:
|
||||||
return "Intel Performance Code";
|
return "Intel Performance Code";
|
||||||
|
|
||||||
case P_ID_INTEL_DATA:
|
case P_ID_INTEL_DATA:
|
||||||
return "Intel Data";
|
return "Intel Data";
|
||||||
|
|
||||||
case P_ID_RESERVED:
|
case P_ID_RESERVED:
|
||||||
return "Not Allowed / Reserved for Future Use";
|
return "Not Allowed / Reserved for Future Use";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@ -325,21 +325,21 @@ static void print_cfi_ident(struct cfi_ident *cfip)
|
|||||||
if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
|
if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
|
||||||
printk("Invalid CFI ident structure.\n");
|
printk("Invalid CFI ident structure.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
|
printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
|
||||||
if (cfip->P_ADR)
|
if (cfip->P_ADR)
|
||||||
printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
|
printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
|
||||||
else
|
else
|
||||||
printk("No Primary Algorithm Table\n");
|
printk("No Primary Algorithm Table\n");
|
||||||
|
|
||||||
printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
|
printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
|
||||||
if (cfip->A_ADR)
|
if (cfip->A_ADR)
|
||||||
printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
|
printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
|
||||||
else
|
else
|
||||||
printk("No Alternate Algorithm Table\n");
|
printk("No Alternate Algorithm Table\n");
|
||||||
|
|
||||||
|
|
||||||
printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
|
printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
|
||||||
printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
|
printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
|
||||||
if (cfip->VppMin) {
|
if (cfip->VppMin) {
|
||||||
@ -348,61 +348,61 @@ static void print_cfi_ident(struct cfi_ident *cfip)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
printk("No Vpp line\n");
|
printk("No Vpp line\n");
|
||||||
|
|
||||||
printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
|
printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
|
||||||
printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
|
printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
|
||||||
|
|
||||||
if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
|
if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
|
||||||
printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
|
printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
|
||||||
printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
|
printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printk("Full buffer write not supported\n");
|
printk("Full buffer write not supported\n");
|
||||||
|
|
||||||
printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
|
printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
|
||||||
printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
|
printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
|
||||||
if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
|
if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
|
||||||
printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp);
|
printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp);
|
||||||
printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
|
printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printk("Chip erase not supported\n");
|
printk("Chip erase not supported\n");
|
||||||
|
|
||||||
printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
|
printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
|
||||||
printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
|
printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
|
||||||
switch(cfip->InterfaceDesc) {
|
switch(cfip->InterfaceDesc) {
|
||||||
case 0:
|
case 0:
|
||||||
printk(" - x8-only asynchronous interface\n");
|
printk(" - x8-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
printk(" - x16-only asynchronous interface\n");
|
printk(" - x16-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
|
printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
printk(" - x32-only asynchronous interface\n");
|
printk(" - x32-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
printk(" - supports x16 and x32 via Word# with asynchronous interface\n");
|
printk(" - supports x16 and x32 via Word# with asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 65535:
|
case 65535:
|
||||||
printk(" - Not Allowed / Reserved\n");
|
printk(" - Not Allowed / Reserved\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printk(" - Unknown\n");
|
printk(" - Unknown\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
|
printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
|
||||||
printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
|
printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* DEBUG_CFI */
|
#endif /* DEBUG_CFI */
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* This code is covered by the GPL.
|
* This code is covered by the GPL.
|
||||||
*
|
*
|
||||||
* $Id: cfi_util.c,v 1.9 2005/07/20 21:01:14 tpoynor Exp $
|
* $Id: cfi_util.c,v 1.10 2005/11/07 11:14:23 gleixner Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
|
|||||||
|
|
||||||
/* Read in the Extended Query Table */
|
/* Read in the Extended Query Table */
|
||||||
for (i=0; i<size; i++) {
|
for (i=0; i<size; i++) {
|
||||||
((unsigned char *)extp)[i] =
|
((unsigned char *)extp)[i] =
|
||||||
cfi_read_query(map, base+((adr+i)*ofs_factor));
|
cfi_read_query(map, base+((adr+i)*ofs_factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,17 +113,17 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
/* Skip all erase regions which are ended before the start of
|
/* Skip all erase regions which are ended before the start of
|
||||||
the requested erase. Actually, to save on the calculations,
|
the requested erase. Actually, to save on the calculations,
|
||||||
we skip to the first erase region which starts after the
|
we skip to the first erase region which starts after the
|
||||||
start of the requested erase, and then go back one.
|
start of the requested erase, and then go back one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (i < mtd->numeraseregions && ofs >= regions[i].offset)
|
while (i < mtd->numeraseregions && ofs >= regions[i].offset)
|
||||||
i++;
|
i++;
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
/* OK, now i is pointing at the erase region in which this
|
/* OK, now i is pointing at the erase region in which this
|
||||||
erase request starts. Check the start of the requested
|
erase request starts. Check the start of the requested
|
||||||
erase range is aligned with the erase size which is in
|
erase range is aligned with the erase size which is in
|
||||||
effect here.
|
effect here.
|
||||||
@ -146,7 +146,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
|
|||||||
the address actually falls
|
the address actually falls
|
||||||
*/
|
*/
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
if ((ofs + len) & (regions[i].erasesize-1))
|
if ((ofs + len) & (regions[i].erasesize-1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
|
|||||||
int size = regions[i].erasesize;
|
int size = regions[i].erasesize;
|
||||||
|
|
||||||
ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
|
ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
|
|||||||
if (adr >> cfi->chipshift) {
|
if (adr >> cfi->chipshift) {
|
||||||
adr = 0;
|
adr = 0;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
|
|
||||||
if (chipnum >= cfi->numchips)
|
if (chipnum >= cfi->numchips)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
|
|||||||
|
|
||||||
list_for_each(pos, &chip_drvs_list) {
|
list_for_each(pos, &chip_drvs_list) {
|
||||||
this = list_entry(pos, typeof(*this), list);
|
this = list_entry(pos, typeof(*this), list);
|
||||||
|
|
||||||
if (!strcmp(this->name, name)) {
|
if (!strcmp(this->name, name)) {
|
||||||
ret = this;
|
ret = this;
|
||||||
break;
|
break;
|
||||||
@ -73,7 +73,7 @@ struct mtd_info *do_map_probe(const char *name, struct map_info *map)
|
|||||||
|
|
||||||
ret = drv->probe(map);
|
ret = drv->probe(map);
|
||||||
|
|
||||||
/* We decrease the use count here. It may have been a
|
/* We decrease the use count here. It may have been a
|
||||||
probe-only module, which is no longer required from this
|
probe-only module, which is no longer required from this
|
||||||
point, having given us a handle on (and increased the use
|
point, having given us a handle on (and increased the use
|
||||||
count of) the actual driver code.
|
count of) the actual driver code.
|
||||||
@ -82,7 +82,7 @@ struct mtd_info *do_map_probe(const char *name, struct map_info *map)
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -25,7 +25,7 @@ struct fwh_xxlock_thunk {
|
|||||||
* so this code has not been tested with interleaved chips,
|
* so this code has not been tested with interleaved chips,
|
||||||
* and will likely fail in that context.
|
* and will likely fail in that context.
|
||||||
*/
|
*/
|
||||||
static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
|
static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
|
||||||
unsigned long adr, int len, void *thunk)
|
unsigned long adr, int len, void *thunk)
|
||||||
{
|
{
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
@ -44,7 +44,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
|
|||||||
* - on 64k boundariesand
|
* - on 64k boundariesand
|
||||||
* - bit 1 set high
|
* - bit 1 set high
|
||||||
* - block lock registers are 4MiB lower - overflow subtract (danger)
|
* - block lock registers are 4MiB lower - overflow subtract (danger)
|
||||||
*
|
*
|
||||||
* The address manipulation is first done on the logical address
|
* The address manipulation is first done on the logical address
|
||||||
* which is 0 at the start of the chip, and then the offset of
|
* which is 0 at the start of the chip, and then the offset of
|
||||||
* the individual chip is addted to it. Any other order a weird
|
* the individual chip is addted to it. Any other order a weird
|
||||||
@ -93,7 +93,7 @@ static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
|
|||||||
|
|
||||||
ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
|
ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
|
||||||
(void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
|
(void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Routines common to all CFI-type probes.
|
* Routines common to all CFI-type probes.
|
||||||
* (C) 2001-2003 Red Hat, Inc.
|
* (C) 2001-2003 Red Hat, Inc.
|
||||||
* GPL'd
|
* GPL'd
|
||||||
* $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $
|
* $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -26,7 +26,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
|
|||||||
|
|
||||||
/* First probe the map to see if we have CFI stuff there. */
|
/* First probe the map to see if we have CFI stuff there. */
|
||||||
cfi = genprobe_ident_chips(map, cp);
|
cfi = genprobe_ident_chips(map, cp);
|
||||||
|
|
||||||
if (!cfi)
|
if (!cfi)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -36,12 +36,12 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
|
|||||||
mtd = check_cmd_set(map, 1); /* First the primary cmdset */
|
mtd = check_cmd_set(map, 1); /* First the primary cmdset */
|
||||||
if (!mtd)
|
if (!mtd)
|
||||||
mtd = check_cmd_set(map, 0); /* Then the secondary */
|
mtd = check_cmd_set(map, 0); /* Then the secondary */
|
||||||
|
|
||||||
if (mtd)
|
if (mtd)
|
||||||
return mtd;
|
return mtd;
|
||||||
|
|
||||||
printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
|
printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
|
||||||
|
|
||||||
kfree(cfi->cfiq);
|
kfree(cfi->cfiq);
|
||||||
kfree(cfi);
|
kfree(cfi);
|
||||||
map->fldrv_priv = NULL;
|
map->fldrv_priv = NULL;
|
||||||
@ -60,14 +60,14 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
|
|||||||
|
|
||||||
memset(&cfi, 0, sizeof(cfi));
|
memset(&cfi, 0, sizeof(cfi));
|
||||||
|
|
||||||
/* Call the probetype-specific code with all permutations of
|
/* Call the probetype-specific code with all permutations of
|
||||||
interleave and device type, etc. */
|
interleave and device type, etc. */
|
||||||
if (!genprobe_new_chip(map, cp, &cfi)) {
|
if (!genprobe_new_chip(map, cp, &cfi)) {
|
||||||
/* The probe didn't like it */
|
/* The probe didn't like it */
|
||||||
printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
|
printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
|
||||||
cp->name, map->name);
|
cp->name, map->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD
|
#if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD
|
||||||
probe routines won't ever return a broken CFI structure anyway,
|
probe routines won't ever return a broken CFI structure anyway,
|
||||||
@ -92,13 +92,13 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
|
|||||||
} else {
|
} else {
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
cfi.numchips = 1;
|
cfi.numchips = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate memory for bitmap of valid chips.
|
* Allocate memory for bitmap of valid chips.
|
||||||
* Align bitmap storage size to full byte.
|
* Align bitmap storage size to full byte.
|
||||||
*/
|
*/
|
||||||
max_chips = map->size >> cfi.chipshift;
|
max_chips = map->size >> cfi.chipshift;
|
||||||
mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
|
mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
|
||||||
chip_map = kmalloc(mapsize, GFP_KERNEL);
|
chip_map = kmalloc(mapsize, GFP_KERNEL);
|
||||||
@ -122,7 +122,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now allocate the space for the structures we need to return to
|
* Now allocate the space for the structures we need to return to
|
||||||
* our caller, and copy the appropriate data into them.
|
* our caller, and copy the appropriate data into them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
|
|||||||
return retcfi;
|
return retcfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
|
static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
|
||||||
struct cfi_private *cfi)
|
struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
@ -189,7 +189,7 @@ extern cfi_cmdset_fn_t cfi_cmdset_0001;
|
|||||||
extern cfi_cmdset_fn_t cfi_cmdset_0002;
|
extern cfi_cmdset_fn_t cfi_cmdset_0002;
|
||||||
extern cfi_cmdset_fn_t cfi_cmdset_0020;
|
extern cfi_cmdset_fn_t cfi_cmdset_0020;
|
||||||
|
|
||||||
static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
|
static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
|
||||||
int primary)
|
int primary)
|
||||||
{
|
{
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
@ -199,7 +199,7 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
|
|||||||
cfi_cmdset_fn_t *probe_function;
|
cfi_cmdset_fn_t *probe_function;
|
||||||
|
|
||||||
sprintf(probename, "cfi_cmdset_%4.4X", type);
|
sprintf(probename, "cfi_cmdset_%4.4X", type);
|
||||||
|
|
||||||
probe_function = inter_module_get_request(probename, probename);
|
probe_function = inter_module_get_request(probename, probename);
|
||||||
|
|
||||||
if (probe_function) {
|
if (probe_function) {
|
||||||
@ -221,7 +221,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
|
|||||||
{
|
{
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
__u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
|
__u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
|
||||||
|
|
||||||
if (type == P_ID_NONE || type == P_ID_RESERVED)
|
if (type == P_ID_NONE || type == P_ID_RESERVED)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
/* JEDEC Flash Interface.
|
/* JEDEC Flash Interface.
|
||||||
* This is an older type of interface for self programming flash. It is
|
* This is an older type of interface for self programming flash. It is
|
||||||
* commonly use in older AMD chips and is obsolete compared with CFI.
|
* commonly use in older AMD chips and is obsolete compared with CFI.
|
||||||
* It is called JEDEC because the JEDEC association distributes the ID codes
|
* It is called JEDEC because the JEDEC association distributes the ID codes
|
||||||
* for the chips.
|
* for the chips.
|
||||||
@ -88,9 +88,9 @@ static const struct JEDECTable JEDEC_table[] = {
|
|||||||
|
|
||||||
static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
|
static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);
|
||||||
static void jedec_sync(struct mtd_info *mtd) {};
|
static void jedec_sync(struct mtd_info *mtd) {};
|
||||||
static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
|
static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf);
|
size_t *retlen, u_char *buf);
|
||||||
static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
|
static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf);
|
size_t *retlen, u_char *buf);
|
||||||
|
|
||||||
static struct mtd_info *jedec_probe(struct map_info *map);
|
static struct mtd_info *jedec_probe(struct map_info *map);
|
||||||
@ -122,7 +122,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
|
|
||||||
memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
|
memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
|
||||||
priv = (struct jedec_private *)&MTD[1];
|
priv = (struct jedec_private *)&MTD[1];
|
||||||
|
|
||||||
my_bank_size = map->size;
|
my_bank_size = map->size;
|
||||||
|
|
||||||
if (map->size/my_bank_size > MAX_JEDEC_CHIPS)
|
if (map->size/my_bank_size > MAX_JEDEC_CHIPS)
|
||||||
@ -131,13 +131,13 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
kfree(MTD);
|
kfree(MTD);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Base = 0; Base < map->size; Base += my_bank_size)
|
for (Base = 0; Base < map->size; Base += my_bank_size)
|
||||||
{
|
{
|
||||||
// Perhaps zero could designate all tests?
|
// Perhaps zero could designate all tests?
|
||||||
if (map->buswidth == 0)
|
if (map->buswidth == 0)
|
||||||
map->buswidth = 1;
|
map->buswidth = 1;
|
||||||
|
|
||||||
if (map->buswidth == 1){
|
if (map->buswidth == 1){
|
||||||
if (jedec_probe8(map,Base,priv) == 0) {
|
if (jedec_probe8(map,Base,priv) == 0) {
|
||||||
printk("did recognize jedec chip\n");
|
printk("did recognize jedec chip\n");
|
||||||
@ -150,7 +150,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
if (map->buswidth == 4)
|
if (map->buswidth == 4)
|
||||||
jedec_probe32(map,Base,priv);
|
jedec_probe32(map,Base,priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the biggest sector size
|
// Get the biggest sector size
|
||||||
SectorSize = 0;
|
SectorSize = 0;
|
||||||
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
||||||
@ -160,7 +160,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
if (priv->chips[I].sectorsize > SectorSize)
|
if (priv->chips[I].sectorsize > SectorSize)
|
||||||
SectorSize = priv->chips[I].sectorsize;
|
SectorSize = priv->chips[I].sectorsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quickly ensure that the other sector sizes are factors of the largest
|
// Quickly ensure that the other sector sizes are factors of the largest
|
||||||
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
||||||
{
|
{
|
||||||
@ -169,9 +169,9 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
|
printk("mtd: Failed. Device has incompatible mixed sector sizes\n");
|
||||||
kfree(MTD);
|
kfree(MTD);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a part name that includes the number of different chips and
|
/* Generate a part name that includes the number of different chips and
|
||||||
other configuration information */
|
other configuration information */
|
||||||
count = 1;
|
count = 1;
|
||||||
@ -181,13 +181,13 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
||||||
{
|
{
|
||||||
const struct JEDECTable *JEDEC;
|
const struct JEDECTable *JEDEC;
|
||||||
|
|
||||||
if (priv->chips[I+1].jedec == priv->chips[I].jedec)
|
if (priv->chips[I+1].jedec == priv->chips[I].jedec)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate the chip in the jedec table
|
// Locate the chip in the jedec table
|
||||||
JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);
|
JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);
|
||||||
if (JEDEC == 0)
|
if (JEDEC == 0)
|
||||||
@ -196,11 +196,11 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
kfree(MTD);
|
kfree(MTD);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Uniq != 0)
|
if (Uniq != 0)
|
||||||
strcat(Part,",");
|
strcat(Part,",");
|
||||||
Uniq++;
|
Uniq++;
|
||||||
|
|
||||||
if (count != 1)
|
if (count != 1)
|
||||||
sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
|
sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);
|
||||||
else
|
else
|
||||||
@ -208,7 +208,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
if (strlen(Part) > sizeof(Part)*2/3)
|
if (strlen(Part) > sizeof(Part)*2/3)
|
||||||
break;
|
break;
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if the chips are organized in a linear fashion, or if there
|
/* Determine if the chips are organized in a linear fashion, or if there
|
||||||
are empty banks. Note, the last bank does not count here, only the
|
are empty banks. Note, the last bank does not count here, only the
|
||||||
@ -233,7 +233,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
{
|
{
|
||||||
if (priv->bank_fill[I] != my_bank_size)
|
if (priv->bank_fill[I] != my_bank_size)
|
||||||
priv->is_banked = 1;
|
priv->is_banked = 1;
|
||||||
|
|
||||||
/* This even could be eliminated, but new de-optimized read/write
|
/* This even could be eliminated, but new de-optimized read/write
|
||||||
functions have to be written */
|
functions have to be written */
|
||||||
printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);
|
printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);
|
||||||
@ -242,7 +242,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
printk("mtd: Failed. Cannot handle unsymmetric banking\n");
|
printk("mtd: Failed. Cannot handle unsymmetric banking\n");
|
||||||
kfree(MTD);
|
kfree(MTD);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ static struct mtd_info *jedec_probe(struct map_info *map)
|
|||||||
strcat(Part,", banked");
|
strcat(Part,", banked");
|
||||||
|
|
||||||
// printk("Part: '%s'\n",Part);
|
// printk("Part: '%s'\n",Part);
|
||||||
|
|
||||||
memset(MTD,0,sizeof(*MTD));
|
memset(MTD,0,sizeof(*MTD));
|
||||||
// strlcpy(MTD->name,Part,sizeof(MTD->name));
|
// strlcpy(MTD->name,Part,sizeof(MTD->name));
|
||||||
MTD->name = map->name;
|
MTD->name = map->name;
|
||||||
@ -291,7 +291,7 @@ static int checkparity(u_char C)
|
|||||||
|
|
||||||
/* Take an array of JEDEC numbers that represent interleved flash chips
|
/* Take an array of JEDEC numbers that represent interleved flash chips
|
||||||
and process them. Check to make sure they are good JEDEC numbers, look
|
and process them. Check to make sure they are good JEDEC numbers, look
|
||||||
them up and then add them to the chip list */
|
them up and then add them to the chip list */
|
||||||
static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
||||||
unsigned long base,struct jedec_private *priv)
|
unsigned long base,struct jedec_private *priv)
|
||||||
{
|
{
|
||||||
@ -306,16 +306,16 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
|||||||
if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
|
if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, just make sure all the chip sizes are the same
|
// Finally, just make sure all the chip sizes are the same
|
||||||
JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
|
JEDEC = jedec_idtoinf(Mfg[0],Id[0]);
|
||||||
|
|
||||||
if (JEDEC == 0)
|
if (JEDEC == 0)
|
||||||
{
|
{
|
||||||
printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
|
printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size = JEDEC->size;
|
Size = JEDEC->size;
|
||||||
SectorSize = JEDEC->sectorsize;
|
SectorSize = JEDEC->sectorsize;
|
||||||
for (I = 0; I != Count; I++)
|
for (I = 0; I != Count; I++)
|
||||||
@ -331,7 +331,7 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
|||||||
{
|
{
|
||||||
printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
|
printk("mtd: Failed. Interleved flash does not have matching characteristics\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the Chips
|
// Load the Chips
|
||||||
@ -345,13 +345,13 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
|||||||
{
|
{
|
||||||
printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
|
printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add them to the table
|
// Add them to the table
|
||||||
for (J = 0; J != Count; J++)
|
for (J = 0; J != Count; J++)
|
||||||
{
|
{
|
||||||
unsigned long Bank;
|
unsigned long Bank;
|
||||||
|
|
||||||
JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
|
JEDEC = jedec_idtoinf(Mfg[J],Id[J]);
|
||||||
priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
|
priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];
|
||||||
priv->chips[I].size = JEDEC->size;
|
priv->chips[I].size = JEDEC->size;
|
||||||
@ -364,17 +364,17 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,
|
|||||||
// log2 n :|
|
// log2 n :|
|
||||||
priv->chips[I].addrshift = 0;
|
priv->chips[I].addrshift = 0;
|
||||||
for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
|
for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);
|
||||||
|
|
||||||
// Determine how filled this bank is.
|
// Determine how filled this bank is.
|
||||||
Bank = base & (~(my_bank_size-1));
|
Bank = base & (~(my_bank_size-1));
|
||||||
if (priv->bank_fill[Bank/my_bank_size] < base +
|
if (priv->bank_fill[Bank/my_bank_size] < base +
|
||||||
(JEDEC->size << priv->chips[I].addrshift) - Bank)
|
(JEDEC->size << priv->chips[I].addrshift) - Bank)
|
||||||
priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
|
priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank;
|
||||||
I++;
|
I++;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->size += priv->chips[I-1].size*Count;
|
priv->size += priv->chips[I-1].size*Count;
|
||||||
|
|
||||||
return priv->chips[I-1].size;
|
return priv->chips[I-1].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id)
|
|||||||
// Look for flash using an 8 bit bus interface
|
// Look for flash using an 8 bit bus interface
|
||||||
static int jedec_probe8(struct map_info *map,unsigned long base,
|
static int jedec_probe8(struct map_info *map,unsigned long base,
|
||||||
struct jedec_private *priv)
|
struct jedec_private *priv)
|
||||||
{
|
{
|
||||||
#define flread(x) map_read8(map,base+x)
|
#define flread(x) map_read8(map,base+x)
|
||||||
#define flwrite(v,x) map_write8(map,v,base+x)
|
#define flwrite(v,x) map_write8(map,v,base+x)
|
||||||
|
|
||||||
@ -410,20 +410,20 @@ static int jedec_probe8(struct map_info *map,unsigned long base,
|
|||||||
OldVal = flread(base);
|
OldVal = flread(base);
|
||||||
for (I = 0; OldVal != flread(base) && I < 10000; I++)
|
for (I = 0; OldVal != flread(base) && I < 10000; I++)
|
||||||
OldVal = flread(base);
|
OldVal = flread(base);
|
||||||
|
|
||||||
// Reset the chip
|
// Reset the chip
|
||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
|
|
||||||
// Send the sequence
|
// Send the sequence
|
||||||
flwrite(AutoSel1,0x555);
|
flwrite(AutoSel1,0x555);
|
||||||
flwrite(AutoSel2,0x2AA);
|
flwrite(AutoSel2,0x2AA);
|
||||||
flwrite(AutoSel3,0x555);
|
flwrite(AutoSel3,0x555);
|
||||||
|
|
||||||
// Get the JEDEC numbers
|
// Get the JEDEC numbers
|
||||||
Mfg[0] = flread(0);
|
Mfg[0] = flread(0);
|
||||||
Id[0] = flread(1);
|
Id[0] = flread(1);
|
||||||
// printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);
|
// printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);
|
||||||
|
|
||||||
Size = handle_jedecs(map,Mfg,Id,1,base,priv);
|
Size = handle_jedecs(map,Mfg,Id,1,base,priv);
|
||||||
// printk("handle_jedecs Size is %x\n",(unsigned int)Size);
|
// printk("handle_jedecs Size is %x\n",(unsigned int)Size);
|
||||||
if (Size == 0)
|
if (Size == 0)
|
||||||
@ -431,13 +431,13 @@ static int jedec_probe8(struct map_info *map,unsigned long base,
|
|||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Reset.
|
// Reset.
|
||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#undef flread
|
#undef flread
|
||||||
#undef flwrite
|
#undef flwrite
|
||||||
}
|
}
|
||||||
@ -470,17 +470,17 @@ static int jedec_probe32(struct map_info *map,unsigned long base,
|
|||||||
OldVal = flread(base);
|
OldVal = flread(base);
|
||||||
for (I = 0; OldVal != flread(base) && I < 10000; I++)
|
for (I = 0; OldVal != flread(base) && I < 10000; I++)
|
||||||
OldVal = flread(base);
|
OldVal = flread(base);
|
||||||
|
|
||||||
// Reset the chip
|
// Reset the chip
|
||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
|
|
||||||
// Send the sequence
|
// Send the sequence
|
||||||
flwrite(AutoSel1,0x555);
|
flwrite(AutoSel1,0x555);
|
||||||
flwrite(AutoSel2,0x2AA);
|
flwrite(AutoSel2,0x2AA);
|
||||||
flwrite(AutoSel3,0x555);
|
flwrite(AutoSel3,0x555);
|
||||||
|
|
||||||
// Test #1, JEDEC numbers are readable from 0x??00/0x??01
|
// Test #1, JEDEC numbers are readable from 0x??00/0x??01
|
||||||
if (flread(0) != flread(0x100) ||
|
if (flread(0) != flread(0x100) ||
|
||||||
flread(1) != flread(0x101))
|
flread(1) != flread(0x101))
|
||||||
{
|
{
|
||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
@ -494,14 +494,14 @@ static int jedec_probe32(struct map_info *map,unsigned long base,
|
|||||||
OldVal = flread(1);
|
OldVal = flread(1);
|
||||||
for (I = 0; I != 4; I++)
|
for (I = 0; I != 4; I++)
|
||||||
Id[I] = (OldVal >> (I*8));
|
Id[I] = (OldVal >> (I*8));
|
||||||
|
|
||||||
Size = handle_jedecs(map,Mfg,Id,4,base,priv);
|
Size = handle_jedecs(map,Mfg,Id,4,base,priv);
|
||||||
if (Size == 0)
|
if (Size == 0)
|
||||||
{
|
{
|
||||||
flwrite(Reset,0x555);
|
flwrite(Reset,0x555);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there is address wrap around within a single bank, if this
|
/* Check if there is address wrap around within a single bank, if this
|
||||||
returns JEDEC numbers then we assume that it is wrap around. Notice
|
returns JEDEC numbers then we assume that it is wrap around. Notice
|
||||||
we call this routine with the JEDEC return still enabled, if two or
|
we call this routine with the JEDEC return still enabled, if two or
|
||||||
@ -519,27 +519,27 @@ static int jedec_probe32(struct map_info *map,unsigned long base,
|
|||||||
|
|
||||||
// Reset.
|
// Reset.
|
||||||
flwrite(0xF0F0F0F0,0x555);
|
flwrite(0xF0F0F0F0,0x555);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#undef flread
|
#undef flread
|
||||||
#undef flwrite
|
#undef flwrite
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linear read. */
|
/* Linear read. */
|
||||||
static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
|
static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf)
|
size_t *retlen, u_char *buf)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
|
|
||||||
map_copy_from(map, buf, from, len);
|
map_copy_from(map, buf, from, len);
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Banked read. Take special care to jump past the holes in the bank
|
/* Banked read. Take special care to jump past the holes in the bank
|
||||||
mapping. This version assumes symetry in the holes.. */
|
mapping. This version assumes symetry in the holes.. */
|
||||||
static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
|
static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf)
|
size_t *retlen, u_char *buf)
|
||||||
{
|
{
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
@ -555,17 +555,17 @@ static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
if (priv->bank_fill[0] - offset < len)
|
if (priv->bank_fill[0] - offset < len)
|
||||||
get = priv->bank_fill[0] - offset;
|
get = priv->bank_fill[0] - offset;
|
||||||
|
|
||||||
bank /= priv->bank_fill[0];
|
bank /= priv->bank_fill[0];
|
||||||
map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get);
|
map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get);
|
||||||
|
|
||||||
len -= get;
|
len -= get;
|
||||||
*retlen += get;
|
*retlen += get;
|
||||||
from += get;
|
from += get;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass the flags value that the flash return before it re-entered read
|
/* Pass the flags value that the flash return before it re-entered read
|
||||||
mode. */
|
mode. */
|
||||||
static void jedec_flash_failed(unsigned char code)
|
static void jedec_flash_failed(unsigned char code)
|
||||||
{
|
{
|
||||||
@ -579,17 +579,17 @@ static void jedec_flash_failed(unsigned char code)
|
|||||||
printk("mtd: Programming didn't take\n");
|
printk("mtd: Programming didn't take\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This uses the erasure function described in the AMD Flash Handbook,
|
/* This uses the erasure function described in the AMD Flash Handbook,
|
||||||
it will work for flashes with a fixed sector size only. Flashes with
|
it will work for flashes with a fixed sector size only. Flashes with
|
||||||
a selection of sector sizes (ie the AMD Am29F800B) will need a different
|
a selection of sector sizes (ie the AMD Am29F800B) will need a different
|
||||||
routine. This routine tries to parallize erasing multiple chips/sectors
|
routine. This routine tries to parallize erasing multiple chips/sectors
|
||||||
where possible */
|
where possible */
|
||||||
static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||||
{
|
{
|
||||||
// Does IO to the currently selected chip
|
// Does IO to the currently selected chip
|
||||||
#define flread(x) map_read8(map,chip->base+((x)<<chip->addrshift))
|
#define flread(x) map_read8(map,chip->base+((x)<<chip->addrshift))
|
||||||
#define flwrite(v,x) map_write8(map,v,chip->base+((x)<<chip->addrshift))
|
#define flwrite(v,x) map_write8(map,v,chip->base+((x)<<chip->addrshift))
|
||||||
|
|
||||||
unsigned long Time = 0;
|
unsigned long Time = 0;
|
||||||
unsigned long NoTime = 0;
|
unsigned long NoTime = 0;
|
||||||
unsigned long start = instr->addr, len = instr->len;
|
unsigned long start = instr->addr, len = instr->len;
|
||||||
@ -603,7 +603,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
(len % mtd->erasesize) != 0 ||
|
(len % mtd->erasesize) != 0 ||
|
||||||
(len/mtd->erasesize) == 0)
|
(len/mtd->erasesize) == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
jedec_flash_chip_scan(priv,start,len);
|
jedec_flash_chip_scan(priv,start,len);
|
||||||
|
|
||||||
// Start the erase sequence on each chip
|
// Start the erase sequence on each chip
|
||||||
@ -611,16 +611,16 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
{
|
{
|
||||||
unsigned long off;
|
unsigned long off;
|
||||||
struct jedec_flash_chip *chip = priv->chips + I;
|
struct jedec_flash_chip *chip = priv->chips + I;
|
||||||
|
|
||||||
if (chip->length == 0)
|
if (chip->length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (chip->start + chip->length > chip->size)
|
if (chip->start + chip->length > chip->size)
|
||||||
{
|
{
|
||||||
printk("DIE\n");
|
printk("DIE\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
flwrite(0xF0,chip->start + 0x555);
|
flwrite(0xF0,chip->start + 0x555);
|
||||||
flwrite(0xAA,chip->start + 0x555);
|
flwrite(0xAA,chip->start + 0x555);
|
||||||
flwrite(0x55,chip->start + 0x2AA);
|
flwrite(0x55,chip->start + 0x2AA);
|
||||||
@ -628,8 +628,8 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
flwrite(0xAA,chip->start + 0x555);
|
flwrite(0xAA,chip->start + 0x555);
|
||||||
flwrite(0x55,chip->start + 0x2AA);
|
flwrite(0x55,chip->start + 0x2AA);
|
||||||
|
|
||||||
/* Once we start selecting the erase sectors the delay between each
|
/* Once we start selecting the erase sectors the delay between each
|
||||||
command must not exceed 50us or it will immediately start erasing
|
command must not exceed 50us or it will immediately start erasing
|
||||||
and ignore the other sectors */
|
and ignore the other sectors */
|
||||||
for (off = 0; off < len; off += chip->sectorsize)
|
for (off = 0; off < len; off += chip->sectorsize)
|
||||||
{
|
{
|
||||||
@ -641,19 +641,19 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
{
|
{
|
||||||
printk("mtd: Ack! We timed out the erase timer!\n");
|
printk("mtd: Ack! We timed out the erase timer!\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We could split this into a timer routine and return early, performing
|
/* We could split this into a timer routine and return early, performing
|
||||||
background erasure.. Maybe later if the need warrents */
|
background erasure.. Maybe later if the need warrents */
|
||||||
|
|
||||||
/* Poll the flash for erasure completion, specs say this can take as long
|
/* Poll the flash for erasure completion, specs say this can take as long
|
||||||
as 480 seconds to do all the sectors (for a 2 meg flash).
|
as 480 seconds to do all the sectors (for a 2 meg flash).
|
||||||
Erasure time is dependent on chip age, temp and wear.. */
|
Erasure time is dependent on chip age, temp and wear.. */
|
||||||
|
|
||||||
/* This being a generic routine assumes a 32 bit bus. It does read32s
|
/* This being a generic routine assumes a 32 bit bus. It does read32s
|
||||||
and bundles interleved chips into the same grouping. This will work
|
and bundles interleved chips into the same grouping. This will work
|
||||||
for all bus widths */
|
for all bus widths */
|
||||||
Time = 0;
|
Time = 0;
|
||||||
NoTime = 0;
|
NoTime = 0;
|
||||||
@ -664,20 +664,20 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
unsigned todo[4] = {0,0,0,0};
|
unsigned todo[4] = {0,0,0,0};
|
||||||
unsigned todo_left = 0;
|
unsigned todo_left = 0;
|
||||||
unsigned J;
|
unsigned J;
|
||||||
|
|
||||||
if (chip->length == 0)
|
if (chip->length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Find all chips in this data line, realistically this is all
|
/* Find all chips in this data line, realistically this is all
|
||||||
or nothing up to the interleve count */
|
or nothing up to the interleve count */
|
||||||
for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
|
for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
|
||||||
{
|
{
|
||||||
if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
|
if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
|
||||||
(chip->base & (~((1<<chip->addrshift)-1))))
|
(chip->base & (~((1<<chip->addrshift)-1))))
|
||||||
{
|
{
|
||||||
todo_left++;
|
todo_left++;
|
||||||
todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
|
todo[priv->chips[J].base & ((1<<chip->addrshift)-1)] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
|
/* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1],
|
||||||
@ -687,7 +687,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
{
|
{
|
||||||
__u32 Last[4];
|
__u32 Last[4];
|
||||||
unsigned long Count = 0;
|
unsigned long Count = 0;
|
||||||
|
|
||||||
/* During erase bit 7 is held low and bit 6 toggles, we watch this,
|
/* During erase bit 7 is held low and bit 6 toggles, we watch this,
|
||||||
should it stop toggling or go high then the erase is completed,
|
should it stop toggling or go high then the erase is completed,
|
||||||
or this is not really flash ;> */
|
or this is not really flash ;> */
|
||||||
@ -718,23 +718,23 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
__u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
|
__u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF;
|
||||||
if (todo[J] == 0)
|
if (todo[J] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
|
if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2)
|
||||||
{
|
{
|
||||||
// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
|
// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Byte1 == Byte2)
|
if (Byte1 == Byte2)
|
||||||
{
|
{
|
||||||
jedec_flash_failed(Byte3);
|
jedec_flash_failed(Byte3);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo[J] = 0;
|
todo[J] = 0;
|
||||||
todo_left--;
|
todo_left--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (NoTime == 0)
|
/* if (NoTime == 0)
|
||||||
Time += HZ/10 - schedule_timeout(HZ/10);*/
|
Time += HZ/10 - schedule_timeout(HZ/10);*/
|
||||||
NoTime = 0;
|
NoTime = 0;
|
||||||
@ -751,7 +751,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Count++;
|
Count++;
|
||||||
|
|
||||||
/* // Count time, max of 15s per sector (according to AMD)
|
/* // Count time, max of 15s per sector (according to AMD)
|
||||||
if (Time > 15*len/mtd->erasesize*HZ)
|
if (Time > 15*len/mtd->erasesize*HZ)
|
||||||
{
|
{
|
||||||
@ -759,38 +759,38 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip to the next chip if we used chip erase
|
// Skip to the next chip if we used chip erase
|
||||||
if (chip->length == chip->size)
|
if (chip->length == chip->size)
|
||||||
off = chip->size;
|
off = chip->size;
|
||||||
else
|
else
|
||||||
off += chip->sectorsize;
|
off += chip->sectorsize;
|
||||||
|
|
||||||
if (off >= chip->length)
|
if (off >= chip->length)
|
||||||
break;
|
break;
|
||||||
NoTime = 1;
|
NoTime = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
|
for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++)
|
||||||
{
|
{
|
||||||
if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
|
if ((priv->chips[J].base & (~((1<<chip->addrshift)-1))) ==
|
||||||
(chip->base & (~((1<<chip->addrshift)-1))))
|
(chip->base & (~((1<<chip->addrshift)-1))))
|
||||||
priv->chips[J].length = 0;
|
priv->chips[J].length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printk("done\n");
|
//printk("done\n");
|
||||||
instr->state = MTD_ERASE_DONE;
|
instr->state = MTD_ERASE_DONE;
|
||||||
mtd_erase_callback(instr);
|
mtd_erase_callback(instr);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#undef flread
|
#undef flread
|
||||||
#undef flwrite
|
#undef flwrite
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the simple flash writing function. It writes to every byte, in
|
/* This is the simple flash writing function. It writes to every byte, in
|
||||||
sequence. It takes care of how to properly address the flash if
|
sequence. It takes care of how to properly address the flash if
|
||||||
the flash is interleved. It can only be used if all the chips in the
|
the flash is interleved. It can only be used if all the chips in the
|
||||||
array are identical!*/
|
array are identical!*/
|
||||||
static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
||||||
size_t *retlen, const u_char *buf)
|
size_t *retlen, const u_char *buf)
|
||||||
@ -800,25 +800,25 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
|||||||
of addrshift (interleave index) and then adds the control register index. */
|
of addrshift (interleave index) and then adds the control register index. */
|
||||||
#define flread(x) map_read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
|
#define flread(x) map_read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
|
||||||
#define flwrite(v,x) map_write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
|
#define flwrite(v,x) map_write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
|
||||||
|
|
||||||
struct map_info *map = mtd->priv;
|
struct map_info *map = mtd->priv;
|
||||||
struct jedec_private *priv = map->fldrv_priv;
|
struct jedec_private *priv = map->fldrv_priv;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
unsigned long off;
|
unsigned long off;
|
||||||
size_t save_len = len;
|
size_t save_len = len;
|
||||||
|
|
||||||
if (start + len > mtd->size)
|
if (start + len > mtd->size)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
//printk("Here");
|
//printk("Here");
|
||||||
|
|
||||||
//printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len);
|
//printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len);
|
||||||
while (len != 0)
|
while (len != 0)
|
||||||
{
|
{
|
||||||
struct jedec_flash_chip *chip = priv->chips;
|
struct jedec_flash_chip *chip = priv->chips;
|
||||||
unsigned long bank;
|
unsigned long bank;
|
||||||
unsigned long boffset;
|
unsigned long boffset;
|
||||||
|
|
||||||
// Compute the base of the flash.
|
// Compute the base of the flash.
|
||||||
off = ((unsigned long)start) % (chip->size << chip->addrshift);
|
off = ((unsigned long)start) % (chip->size << chip->addrshift);
|
||||||
base = start - off;
|
base = start - off;
|
||||||
@ -828,10 +828,10 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
|||||||
boffset = base & (priv->bank_fill[0]-1);
|
boffset = base & (priv->bank_fill[0]-1);
|
||||||
bank = (bank/priv->bank_fill[0])*my_bank_size;
|
bank = (bank/priv->bank_fill[0])*my_bank_size;
|
||||||
base = bank + boffset;
|
base = bank + boffset;
|
||||||
|
|
||||||
// printk("Flasing %X %X %X\n",base,chip->size,len);
|
// printk("Flasing %X %X %X\n",base,chip->size,len);
|
||||||
// printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift);
|
// printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift);
|
||||||
|
|
||||||
// Loop over this page
|
// Loop over this page
|
||||||
for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
|
for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++)
|
||||||
{
|
{
|
||||||
@ -845,7 +845,7 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
|||||||
}
|
}
|
||||||
if (((~oldbyte) & *buf) != 0)
|
if (((~oldbyte) & *buf) != 0)
|
||||||
printk("mtd: warn: Trying to set a 0 to a 1\n");
|
printk("mtd: warn: Trying to set a 0 to a 1\n");
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
flwrite(0xAA,0x555);
|
flwrite(0xAA,0x555);
|
||||||
flwrite(0x55,0x2AA);
|
flwrite(0x55,0x2AA);
|
||||||
@ -854,10 +854,10 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
|||||||
Last[0] = map_read8(map,base + off);
|
Last[0] = map_read8(map,base + off);
|
||||||
Last[1] = map_read8(map,base + off);
|
Last[1] = map_read8(map,base + off);
|
||||||
Last[2] = map_read8(map,base + off);
|
Last[2] = map_read8(map,base + off);
|
||||||
|
|
||||||
/* Wait for the flash to finish the operation. We store the last 4
|
/* Wait for the flash to finish the operation. We store the last 4
|
||||||
status bytes that have been retrieved so we can determine why
|
status bytes that have been retrieved so we can determine why
|
||||||
it failed. The toggle bits keep toggling when there is a
|
it failed. The toggle bits keep toggling when there is a
|
||||||
failure */
|
failure */
|
||||||
for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
|
for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
|
||||||
Count < 10000; Count++)
|
Count < 10000; Count++)
|
||||||
@ -866,7 +866,7 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
|
|||||||
{
|
{
|
||||||
jedec_flash_failed(Last[(Count - 3) % 4]);
|
jedec_flash_failed(Last[(Count - 3) % 4]);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*retlen = save_len;
|
*retlen = save_len;
|
||||||
@ -885,24 +885,24 @@ static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start
|
|||||||
// Zero the records
|
// Zero the records
|
||||||
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
||||||
priv->chips[I].start = priv->chips[I].length = 0;
|
priv->chips[I].start = priv->chips[I].length = 0;
|
||||||
|
|
||||||
// Intersect the region with each chip
|
// Intersect the region with each chip
|
||||||
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)
|
||||||
{
|
{
|
||||||
struct jedec_flash_chip *chip = priv->chips + I;
|
struct jedec_flash_chip *chip = priv->chips + I;
|
||||||
unsigned long ByteStart;
|
unsigned long ByteStart;
|
||||||
unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
|
unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift);
|
||||||
|
|
||||||
// End is before this chip or the start is after it
|
// End is before this chip or the start is after it
|
||||||
if (start+len < chip->offset ||
|
if (start+len < chip->offset ||
|
||||||
ChipEndByte - (1 << chip->addrshift) < start)
|
ChipEndByte - (1 << chip->addrshift) < start)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (start < chip->offset)
|
if (start < chip->offset)
|
||||||
{
|
{
|
||||||
ByteStart = chip->offset;
|
ByteStart = chip->offset;
|
||||||
chip->start = 0;
|
chip->start = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
|
chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Common Flash Interface probe code.
|
Common Flash Interface probe code.
|
||||||
(C) 2000 Red Hat. GPL'd.
|
(C) 2000 Red Hat. GPL'd.
|
||||||
$Id: jedec_probe.c,v 1.63 2005/02/14 16:30:32 bjd Exp $
|
$Id: jedec_probe.c,v 1.66 2005/11/07 11:14:23 gleixner Exp $
|
||||||
See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
|
See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
|
||||||
for the standard this probe goes back to.
|
for the standard this probe goes back to.
|
||||||
|
|
||||||
@ -1719,7 +1719,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
|
|
||||||
static struct mtd_info *jedec_probe(struct map_info *map);
|
static struct mtd_info *jedec_probe(struct map_info *map);
|
||||||
|
|
||||||
static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
|
static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
|
||||||
struct cfi_private *cfi)
|
struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
map_word result;
|
map_word result;
|
||||||
@ -1730,7 +1730,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
|
|||||||
return result.x[0] & mask;
|
return result.x[0] & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 jedec_read_id(struct map_info *map, __u32 base,
|
static inline u32 jedec_read_id(struct map_info *map, __u32 base,
|
||||||
struct cfi_private *cfi)
|
struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
map_word result;
|
map_word result;
|
||||||
@ -1741,7 +1741,7 @@ static inline u32 jedec_read_id(struct map_info *map, __u32 base,
|
|||||||
return result.x[0] & mask;
|
return result.x[0] & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void jedec_reset(u32 base, struct map_info *map,
|
static inline void jedec_reset(u32 base, struct map_info *map,
|
||||||
struct cfi_private *cfi)
|
struct cfi_private *cfi)
|
||||||
{
|
{
|
||||||
/* Reset */
|
/* Reset */
|
||||||
@ -1765,7 +1765,7 @@ static inline void jedec_reset(u32 base, struct map_info *map,
|
|||||||
* so ensure we're in read mode. Send both the Intel and the AMD command
|
* so ensure we're in read mode. Send both the Intel and the AMD command
|
||||||
* for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
|
* for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
|
||||||
* this should be safe.
|
* this should be safe.
|
||||||
*/
|
*/
|
||||||
cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
|
||||||
/* FIXME - should have reset delay before continuing */
|
/* FIXME - should have reset delay before continuing */
|
||||||
}
|
}
|
||||||
@ -1807,14 +1807,14 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
|
|||||||
printk("Found: %s\n",jedec_table[index].name);
|
printk("Found: %s\n",jedec_table[index].name);
|
||||||
|
|
||||||
num_erase_regions = jedec_table[index].NumEraseRegions;
|
num_erase_regions = jedec_table[index].NumEraseRegions;
|
||||||
|
|
||||||
p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
|
p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
|
||||||
if (!p_cfi->cfiq) {
|
if (!p_cfi->cfiq) {
|
||||||
//xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
|
//xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
|
memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
|
||||||
|
|
||||||
p_cfi->cfiq->P_ID = jedec_table[index].CmdSet;
|
p_cfi->cfiq->P_ID = jedec_table[index].CmdSet;
|
||||||
p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions;
|
p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions;
|
||||||
@ -1969,7 +1969,7 @@ static inline int jedec_match( __u32 base,
|
|||||||
cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
|
cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
|
||||||
/* FIXME - should have a delay before continuing */
|
/* FIXME - should have a delay before continuing */
|
||||||
|
|
||||||
match_done:
|
match_done:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1998,23 +1998,23 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
"Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
|
"Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
|
||||||
base, map->size -1);
|
base, map->size -1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Ensure the unlock addresses we try stay inside the map */
|
/* Ensure the unlock addresses we try stay inside the map */
|
||||||
probe_offset1 = cfi_build_cmd_addr(
|
probe_offset1 = cfi_build_cmd_addr(
|
||||||
cfi->addr_unlock1,
|
cfi->addr_unlock1,
|
||||||
cfi_interleave(cfi),
|
cfi_interleave(cfi),
|
||||||
cfi->device_type);
|
cfi->device_type);
|
||||||
probe_offset2 = cfi_build_cmd_addr(
|
probe_offset2 = cfi_build_cmd_addr(
|
||||||
cfi->addr_unlock1,
|
cfi->addr_unlock1,
|
||||||
cfi_interleave(cfi),
|
cfi_interleave(cfi),
|
||||||
cfi->device_type);
|
cfi->device_type);
|
||||||
if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
|
if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
|
||||||
((base + probe_offset2 + map_bankwidth(map)) >= map->size))
|
((base + probe_offset2 + map_bankwidth(map)) >= map->size))
|
||||||
{
|
{
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset */
|
/* Reset */
|
||||||
jedec_reset(base, map, cfi);
|
jedec_reset(base, map, cfi);
|
||||||
|
|
||||||
@ -2027,13 +2027,13 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
/* FIXME - should have a delay before continuing */
|
/* FIXME - should have a delay before continuing */
|
||||||
|
|
||||||
if (!cfi->numchips) {
|
if (!cfi->numchips) {
|
||||||
/* This is the first time we're called. Set up the CFI
|
/* This is the first time we're called. Set up the CFI
|
||||||
stuff accordingly and return */
|
stuff accordingly and return */
|
||||||
|
|
||||||
cfi->mfr = jedec_read_mfr(map, base, cfi);
|
cfi->mfr = jedec_read_mfr(map, base, cfi);
|
||||||
cfi->id = jedec_read_id(map, base, cfi);
|
cfi->id = jedec_read_id(map, base, cfi);
|
||||||
DEBUG(MTD_DEBUG_LEVEL3,
|
DEBUG(MTD_DEBUG_LEVEL3,
|
||||||
"Search for id:(%02x %02x) interleave(%d) type(%d)\n",
|
"Search for id:(%02x %02x) interleave(%d) type(%d)\n",
|
||||||
cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
|
cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
|
||||||
for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
|
for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
|
||||||
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
|
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
|
||||||
@ -2062,7 +2062,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check each previous chip locations to see if it's an alias */
|
/* Check each previous chip locations to see if it's an alias */
|
||||||
for (i=0; i < (base >> cfi->chipshift); i++) {
|
for (i=0; i < (base >> cfi->chipshift); i++) {
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
@ -2083,7 +2083,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
map->name, base, start);
|
map->name, base, start);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Yes, it's actually got the device IDs as data. Most
|
/* Yes, it's actually got the device IDs as data. Most
|
||||||
* unfortunate. Stick the new chip in read mode
|
* unfortunate. Stick the new chip in read mode
|
||||||
* too and if it's the same, assume it's an alias. */
|
* too and if it's the same, assume it's an alias. */
|
||||||
@ -2097,20 +2097,20 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK, if we got to here, then none of the previous chips appear to
|
/* OK, if we got to here, then none of the previous chips appear to
|
||||||
be aliases for the current one. */
|
be aliases for the current one. */
|
||||||
set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
|
set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
|
||||||
cfi->numchips++;
|
cfi->numchips++;
|
||||||
|
|
||||||
ok_out:
|
ok_out:
|
||||||
/* Put it back into Read Mode */
|
/* Put it back into Read Mode */
|
||||||
jedec_reset(base, map, cfi);
|
jedec_reset(base, map, cfi);
|
||||||
|
|
||||||
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\n",
|
||||||
map->name, cfi_interleave(cfi), cfi->device_type*8, base,
|
map->name, cfi_interleave(cfi), cfi->device_type*8, base,
|
||||||
map->bankwidth*8);
|
map->bankwidth*8);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Common code to handle absent "placeholder" devices
|
* Common code to handle absent "placeholder" devices
|
||||||
* Copyright 2001 Resilience Corporation <ebrower@resilience.com>
|
* Copyright 2001 Resilience Corporation <ebrower@resilience.com>
|
||||||
* $Id: map_absent.c,v 1.5 2004/11/16 18:29:00 dwmw2 Exp $
|
* $Id: map_absent.c,v 1.6 2005/11/07 11:14:23 gleixner Exp $
|
||||||
*
|
*
|
||||||
* This map driver is used to allocate "placeholder" MTD
|
* This map driver is used to allocate "placeholder" MTD
|
||||||
* devices on systems that have socketed/removable media.
|
* devices on systems that have socketed/removable media.
|
||||||
* Use of this driver as a fallback preserves the expected
|
* Use of this driver as a fallback preserves the expected
|
||||||
* registration of MTD device nodes regardless of probe outcome.
|
* registration of MTD device nodes regardless of probe outcome.
|
||||||
* A usage example is as follows:
|
* A usage example is as follows:
|
||||||
*
|
*
|
||||||
@ -80,7 +80,7 @@ static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t
|
|||||||
static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
|
static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
|
||||||
{
|
{
|
||||||
*retlen = 0;
|
*retlen = 0;
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int map_absent_erase(struct mtd_info *mtd, struct erase_info *instr)
|
static int map_absent_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright 2000,2001 David A. Schleef <ds@schleef.org>
|
* Copyright 2000,2001 David A. Schleef <ds@schleef.org>
|
||||||
* 2000,2001 Lineo, Inc.
|
* 2000,2001 Lineo, Inc.
|
||||||
*
|
*
|
||||||
* $Id: sharp.c,v 1.15 2005/08/02 20:36:05 tpoynor Exp $
|
* $Id: sharp.c,v 1.16 2005/11/07 11:14:23 gleixner Exp $
|
||||||
*
|
*
|
||||||
* Devices supported:
|
* Devices supported:
|
||||||
* LH28F016SCT Symmetrical block flash memory, 2Mx8
|
* LH28F016SCT Symmetrical block flash memory, 2Mx8
|
||||||
@ -459,12 +459,12 @@ static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
|
|||||||
remove_wait_queue(&chip->wq, &wait);
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
|
||||||
//spin_lock_bh(chip->mutex);
|
//spin_lock_bh(chip->mutex);
|
||||||
|
|
||||||
if (signal_pending(current)){
|
if (signal_pending(current)){
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ret = -ETIME;
|
ret = -ETIME;
|
||||||
out:
|
out:
|
||||||
@ -563,7 +563,7 @@ static int sharp_suspend(struct mtd_info *mtd)
|
|||||||
static void sharp_resume(struct mtd_info *mtd)
|
static void sharp_resume(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
printk("sharp_resume()\n");
|
printk("sharp_resume()\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sharp_destroy(struct mtd_info *mtd)
|
static void sharp_destroy(struct mtd_info *mtd)
|
||||||
|
Loading…
Reference in New Issue
Block a user