Skip to content

Commit

Permalink
Merge git://git.infradead.org/mtd-2.6
Browse files Browse the repository at this point in the history
* git://git.infradead.org/mtd-2.6:
  [MTD] Use SEEK_{SET,CUR,END} instead of hardcoded values in mtdchar lseek()
  MTD: Fix bug in fixup_convert_atmel_pri
  [JFFS2][SUMMARY] Fix a summary collecting bug.
  [PATCH] [MTD] DEVICES: Fill more device IDs in the structure of m25p80
  MTD: Add lock/unlock operations for Atmel AT49BV6416
  MTD: Convert Atmel PRI information to AMD format
  fs/jffs2/xattr.c: remove dead code
  [PATCH] [MTD] Maps: Add dependency on alternate probe methods to physmap
  [PATCH] MTD: Add Macronix MX29F040 to JEDEC
  [MTD] Fixes of performance and stability issues in CFI driver.
  block2mtd.c: Make kernel boot command line arguments work (try 4)
  [MTD NAND] Fix lookup error in nand_get_flash_type()
  remove #error on !PCI from pmc551.c
  MTD: [NAND] Fix the sharpsl driver after breakage from a core conversion
  [MTD] NAND: OOB buffer offset fixups
  make fs/jffs2/nodelist.c:jffs2_obsolete_node_frag() static
  [PATCH] [MTD] NAND: fix dead URL in Kconfig
  • Loading branch information
Linus Torvalds committed Sep 19, 2006
2 parents 833f732 + ea59830 commit ab5cfd2
Show file tree
Hide file tree
Showing 15 changed files with 271 additions and 103 deletions.
87 changes: 43 additions & 44 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip,

static int __xipram xip_wait_for_operation(
struct map_info *map, struct flchip *chip,
unsigned long adr, int *chip_op_time )
unsigned long adr, unsigned int chip_op_time )
{
struct cfi_private *cfi = map->fldrv_priv;
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
Expand All @@ -917,7 +917,7 @@ static int __xipram xip_wait_for_operation(
flstate_t oldstate, newstate;

start = xip_currtime();
usec = *chip_op_time * 8;
usec = chip_op_time * 8;
if (usec == 0)
usec = 500000;
done = 0;
Expand Down Expand Up @@ -1027,8 +1027,8 @@ static int __xipram xip_wait_for_operation(
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
INVALIDATE_CACHED_RANGE(map, from, size)

#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
xip_wait_for_operation(map, chip, cmd_adr, p_usec)
#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
xip_wait_for_operation(map, chip, cmd_adr, usec)

#else

Expand All @@ -1040,64 +1040,64 @@ static int __xipram xip_wait_for_operation(
static int inval_cache_and_wait_for_operation(
struct map_info *map, struct flchip *chip,
unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
int *chip_op_time )
unsigned int chip_op_time)
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status, status_OK = CMD(0x80);
int z, chip_state = chip->state;
unsigned long timeo;
int chip_state = chip->state;
unsigned int timeo, sleep_time;

spin_unlock(chip->mutex);
if (inval_len)
INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
if (*chip_op_time)
cfi_udelay(*chip_op_time);
spin_lock(chip->mutex);

timeo = *chip_op_time * 8 * HZ / 1000000;
if (timeo < HZ/2)
timeo = HZ/2;
timeo += jiffies;
/* set our timeout to 8 times the expected delay */
timeo = chip_op_time * 8;
if (!timeo)
timeo = 500000;
sleep_time = chip_op_time / 2;

z = 0;
for (;;) {
if (chip->state != chip_state) {
/* Someone's suspended the operation: sleep */
DECLARE_WAITQUEUE(wait, current);

set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex);
schedule();
remove_wait_queue(&chip->wq, &wait);
timeo = jiffies + (HZ / 2); /* FIXME */
spin_lock(chip->mutex);
continue;
}

status = map_read(map, cmd_adr);
if (map_word_andequal(map, status, status_OK, status_OK))
break;

/* OK Still waiting */
if (time_after(jiffies, timeo)) {
if (!timeo) {
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
return -ETIME;
}

/* Latency issues. Drop the lock, wait a while and retry */
z++;
/* OK Still waiting. Drop the lock, wait a while and retry. */
spin_unlock(chip->mutex);
cfi_udelay(1);
if (sleep_time >= 1000000/HZ) {
/*
* Half of the normal delay still remaining
* can be performed with a sleeping delay instead
* of busy waiting.
*/
msleep(sleep_time/1000);
timeo -= sleep_time;
sleep_time = 1000000/HZ;
} else {
udelay(1);
cond_resched();
timeo--;
}
spin_lock(chip->mutex);
}

if (!z) {
if (!--(*chip_op_time))
*chip_op_time = 1;
} else if (z > 1)
++(*chip_op_time);
if (chip->state != chip_state) {
/* Someone's suspended the operation: sleep */
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex);
schedule();
remove_wait_queue(&chip->wq, &wait);
spin_lock(chip->mutex);
}
}

/* Done and happy. */
chip->state = FL_STATUS;
Expand All @@ -1107,8 +1107,7 @@ static int inval_cache_and_wait_for_operation(
#endif

#define WAIT_TIMEOUT(map, chip, adr, udelay) \
({ int __udelay = (udelay); \
INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);


static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
Expand Down Expand Up @@ -1332,7 +1331,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,

ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, map_bankwidth(map),
&chip->word_write_time);
chip->word_write_time);
if (ret) {
xip_enable(map, chip, adr);
printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
Expand Down Expand Up @@ -1569,7 +1568,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,

ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
adr, len,
&chip->buffer_write_time);
chip->buffer_write_time);
if (ret) {
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
Expand Down Expand Up @@ -1704,7 +1703,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,

ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
adr, len,
&chip->erase_time);
chip->erase_time);
if (ret) {
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
Expand Down
111 changes: 111 additions & 0 deletions drivers/mtd/chips/cfi_cmdset_0002.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@
#define MAX_WORD_RETRIES 3

#define MANUFACTURER_AMD 0x0001
#define MANUFACTURER_ATMEL 0x001F
#define MANUFACTURER_SST 0x00BF
#define SST49LF004B 0x0060
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6

static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
Expand All @@ -68,6 +70,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
#include "fwh_lock.h"

static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);

static struct mtd_chip_driver cfi_amdstd_chipdrv = {
.probe = NULL, /* Not usable directly */
.destroy = cfi_amdstd_destroy,
Expand Down Expand Up @@ -161,6 +166,26 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
}
}

/* Atmel chips don't use the same PRI format as AMD chips */
static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
struct cfi_pri_atmel atmel_pri;

memcpy(&atmel_pri, extp, sizeof(atmel_pri));
memset((char *)extp + 5, 0, sizeof(*extp) - 5);

if (atmel_pri.Features & 0x02)
extp->EraseSuspend = 2;

if (atmel_pri.BottomBoot)
extp->TopBottom = 2;
else
extp->TopBottom = 3;
}

static void fixup_use_secsi(struct mtd_info *mtd, void *param)
{
/* Setup for chips with a secsi area */
Expand All @@ -179,6 +204,16 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)

}

/*
* Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors
* locked by default.
*/
static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
{
mtd->lock = cfi_atmel_lock;
mtd->unlock = cfi_atmel_unlock;
}

static struct cfi_fixup cfi_fixup_table[] = {
#ifdef AMD_BOOTLOC_BUG
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
Expand All @@ -192,6 +227,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
#if !FORCE_WORD_WRITE
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
#endif
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
{ 0, 0, NULL, NULL }
};
static struct cfi_fixup jedec_fixup_table[] = {
Expand All @@ -207,6 +243,7 @@ static struct cfi_fixup fixup_table[] = {
* we know that is the case.
*/
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
{ 0, 0, NULL, NULL }
};

Expand Down Expand Up @@ -1607,6 +1644,80 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
return 0;
}

static int do_atmel_lock(struct map_info *map, struct flchip *chip,
unsigned long adr, int len, void *thunk)
{
struct cfi_private *cfi = map->fldrv_priv;
int ret;

spin_lock(chip->mutex);
ret = get_chip(map, chip, adr + chip->start, FL_LOCKING);
if (ret)
goto out_unlock;
chip->state = FL_LOCKING;

DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
__func__, adr, len);

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(0x80, 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);
map_write(map, CMD(0x40), chip->start + adr);

chip->state = FL_READY;
put_chip(map, chip, adr + chip->start);
ret = 0;

out_unlock:
spin_unlock(chip->mutex);
return ret;
}

static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
unsigned long adr, int len, void *thunk)
{
struct cfi_private *cfi = map->fldrv_priv;
int ret;

spin_lock(chip->mutex);
ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING);
if (ret)
goto out_unlock;
chip->state = FL_UNLOCKING;

DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
__func__, adr, len);

cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
map_write(map, CMD(0x70), adr);

chip->state = FL_READY;
put_chip(map, chip, adr + chip->start);
ret = 0;

out_unlock:
spin_unlock(chip->mutex);
return ret;
}

static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL);
}

static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
}


static void cfi_amdstd_sync (struct mtd_info *mtd)
{
Expand Down
14 changes: 14 additions & 0 deletions drivers/mtd/chips/jedec_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
#define MX29LV040C 0x004F
#define MX29LV160T 0x22C4
#define MX29LV160B 0x2249
#define MX29F040 0x00A4
#define MX29F016 0x00AD
#define MX29F002T 0x00B0
#define MX29F004T 0x0045
Expand Down Expand Up @@ -1171,6 +1172,19 @@ static const struct amd_flash_info jedec_table[] = {
ERASEINFO(0x10000,31)
}
}, {
.mfr_id = MANUFACTURER_MACRONIX,
.dev_id = MX29F040,
.name = "Macronix MX29F040",
.uaddr = {
[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
},
.DevSize = SIZE_512KiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 1,
.regions = {
ERASEINFO(0x10000,8),
}
}, {
.mfr_id = MANUFACTURER_MACRONIX,
.dev_id = MX29F016,
.name = "Macronix MX29F016",
Expand Down
Loading

0 comments on commit ab5cfd2

Please sign in to comment.