Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab5cfd2a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
parents 833f7329 ea59830d
Loading
Loading
Loading
Loading
+43 −44
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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

@@ -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);
		spin_lock(chip->mutex);
		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;
@@ -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)
@@ -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);
@@ -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;
@@ -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;
+111 −0
Original line number Diff line number Diff line
@@ -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 *);
@@ -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,
@@ -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 */
@@ -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 },
@@ -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[] = {
@@ -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 }
};

@@ -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)
{
+14 −0
Original line number Diff line number Diff line
@@ -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
@@ -1170,6 +1171,19 @@ static const struct amd_flash_info jedec_table[] = {
			ERASEINFO(0x08000,1),
			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,
+63 −30
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/mtd/mtd.h>
#include <linux/buffer_head.h>
#include <linux/mutex.h>
#include <linux/mount.h>

#define VERSION "$Revision: 1.30 $"

@@ -236,6 +237,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
	}
	return 0;
}


static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
		size_t *retlen, const u_char *buf)
{
@@ -299,6 +302,19 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)

	/* Get a handle on the device */
	bdev = open_bdev_excl(devname, O_RDWR, NULL);
#ifndef MODULE
	if (IS_ERR(bdev)) {

		/* We might not have rootfs mounted at this point. Try
		   to resolve the device name by other means. */

		dev_t dev = name_to_dev_t(devname);
		if (dev != 0) {
			bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ);
		}
	}
#endif

	if (IS_ERR(bdev)) {
		ERROR("error: cannot open device %s", devname);
		goto devinit_err;
@@ -393,26 +409,6 @@ static int parse_num(size_t *num, const char *token)
}


static int parse_name(char **pname, const char *token, size_t limit)
{
	size_t len;
	char *name;

	len = strlen(token) + 1;
	if (len > limit)
		return -ENOSPC;

	name = kmalloc(len, GFP_KERNEL);
	if (!name)
		return -ENOMEM;

	strcpy(name, token);

	*pname = name;
	return 0;
}


static inline void kill_final_newline(char *str)
{
	char *newline = strrchr(str, '\n');
@@ -426,7 +422,13 @@ static inline void kill_final_newline(char *str)
	return 0;				\
} while (0)

static int block2mtd_setup(const char *val, struct kernel_param *kp)
#ifndef MODULE
static int block2mtd_init_called = 0;
static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
#endif


static int block2mtd_setup2(const char *val)
{
	char buf[80 + 12]; /* 80 for device, 12 for erase size */
	char *str = buf;
@@ -450,13 +452,9 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp)
	if (!token[0])
		parse_err("no argument");

	ret = parse_name(&name, token[0], 80);
	if (ret == -ENOMEM)
		parse_err("out of memory");
	if (ret == -ENOSPC)
		parse_err("name too long");
	if (ret)
		return 0;
	name = token[0];
	if (strlen(name) + 1 > 80)
		parse_err("device name too long");

	if (token[1]) {
		ret = parse_num(&erase_size, token[1]);
@@ -472,13 +470,48 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp)
}


static int block2mtd_setup(const char *val, struct kernel_param *kp)
{
#ifdef MODULE
	return block2mtd_setup2(val);
#else
	/* If more parameters are later passed in via
	   /sys/module/block2mtd/parameters/block2mtd
	   and block2mtd_init() has already been called,
	   we can parse the argument now. */

	if (block2mtd_init_called)
		return block2mtd_setup2(val);

	/* During early boot stage, we only save the parameters
	   here. We must parse them later: if the param passed
	   from kernel boot command line, block2mtd_setup() is
	   called so early that it is not possible to resolve
	   the device (even kmalloc() fails). Deter that work to
	   block2mtd_setup2(). */

	strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline));

	return 0;
#endif
}


module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");

static int __init block2mtd_init(void)
{
	int ret = 0;
	INFO("version " VERSION);
	return 0;

#ifndef MODULE
	if (strlen(block2mtd_paramline))
		ret = block2mtd_setup2(block2mtd_paramline);
	block2mtd_init_called = 1;
#endif

	return ret;
}


+6 −6
Original line number Diff line number Diff line
@@ -406,13 +406,13 @@ struct flash_info {

static struct flash_info __devinitdata m25p_data [] = {
	/* REVISIT: fill in JEDEC ids, for parts that have them */
	{ "m25p05", 0x05, 0x0000, 32 * 1024, 2 },
	{ "m25p10", 0x10, 0x0000, 32 * 1024, 4 },
	{ "m25p20", 0x11, 0x0000, 64 * 1024, 4 },
	{ "m25p40", 0x12, 0x0000, 64 * 1024, 8 },
	{ "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
	{ "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
	{ "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
	{ "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
	{ "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
	{ "m25p16", 0x14, 0x0000, 64 * 1024, 32 },
	{ "m25p32", 0x15, 0x0000, 64 * 1024, 64 },
	{ "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
	{ "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
	{ "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
};

Loading