MTD fixes for 3.9

This fixes a couple of problems. Firstly, some people are actually still
 using old small-page flash and we broke it by removing the ready check.
 
 Secondly. fix the handling of partitions on Broadcom 47xx devices.
 Recent changes had made it misdetect the location of the NVRAM and
 scribble over the bootloader when it tried to update the variables there.
 With predictably sad results.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.13 (GNU/Linux)
 
 iEYEABECAAYFAlFG/koACgkQdwG7hYl686OShQCgyOXCXhTltBJU3wHDtTeT1rc9
 Vx0AoL655JpZaUf+BpPsCSTagH4k28vQ
 =OK6b
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-20130318' of git://git.infradead.org/linux-mtd

Pull MTD fixes from David Woodhouse:
 "This fixes a couple of problems.  Firstly, some people are actually
  still using old small-page flash and we broke it by removing the ready
  check.

  Secondly.  fix the handling of partitions on Broadcom 47xx devices.
  Recent changes had made it misdetect the location of the NVRAM and
  scribble over the bootloader when it tried to update the variables
  there.  With predictably sad results."

* tag 'for-linus-20130318' of git://git.infradead.org/linux-mtd:
  mtd: nand: reintroduce NAND_NO_READRDY as NAND_NEED_READRDY
  mtd: bcm47xxpart: look for NVRAM at the end of device
  Revert "mtd: bcm47xxpart: improve probing of nvram partition"
This commit is contained in:
Linus Torvalds 2013-03-18 08:27:41 -07:00
commit 35f8c769aa
4 changed files with 92 additions and 53 deletions

View File

@ -19,6 +19,12 @@
/* 10 parts were found on sflash on Netgear WNDR4500 */
#define BCM47XXPART_MAX_PARTS 12
/*
* Amount of bytes we read when analyzing each block of flash memory.
* Set it big enough to allow detecting partition and reading important data.
*/
#define BCM47XXPART_BYTES_TO_READ 0x404
/* Magics */
#define BOARD_DATA_MAGIC 0x5246504D /* MPFR */
#define POT_MAGIC1 0x54544f50 /* POTT */
@ -57,17 +63,15 @@ static int bcm47xxpart_parse(struct mtd_info *master,
struct trx_header *trx;
int trx_part = -1;
int last_trx_part = -1;
int max_bytes_to_read = 0x8004;
int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
if (blocksize <= 0x10000)
blocksize = 0x10000;
if (blocksize == 0x20000)
max_bytes_to_read = 0x18004;
/* Alloc */
parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
GFP_KERNEL);
buf = kzalloc(max_bytes_to_read, GFP_KERNEL);
buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL);
/* Parse block by block looking for magics */
for (offset = 0; offset <= master->size - blocksize;
@ -82,7 +86,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
}
/* Read beginning of the block */
if (mtd_read(master, offset, max_bytes_to_read,
if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
&bytes_read, (uint8_t *)buf) < 0) {
pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
offset);
@ -96,20 +100,6 @@ static int bcm47xxpart_parse(struct mtd_info *master,
continue;
}
/* Standard NVRAM */
if (buf[0x000 / 4] == NVRAM_HEADER ||
buf[0x1000 / 4] == NVRAM_HEADER ||
buf[0x8000 / 4] == NVRAM_HEADER ||
(blocksize == 0x20000 && (
buf[0x10000 / 4] == NVRAM_HEADER ||
buf[0x11000 / 4] == NVRAM_HEADER ||
buf[0x18000 / 4] == NVRAM_HEADER))) {
bcm47xxpart_add_part(&parts[curr_part++], "nvram",
offset, 0);
offset = rounddown(offset, blocksize);
continue;
}
/*
* board_data starts with board_id which differs across boards,
* but we can use 'MPFR' (hopefully) magic at 0x100
@ -178,6 +168,30 @@ static int bcm47xxpart_parse(struct mtd_info *master,
continue;
}
}
/* Look for NVRAM at the end of the last block. */
for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) {
if (curr_part > BCM47XXPART_MAX_PARTS) {
pr_warn("Reached maximum number of partitions, scanning stopped!\n");
break;
}
offset = master->size - possible_nvram_sizes[i];
if (mtd_read(master, offset, 0x4, &bytes_read,
(uint8_t *)buf) < 0) {
pr_err("mtd_read error while reading at offset 0x%X!\n",
offset);
continue;
}
/* Standard NVRAM */
if (buf[0] == NVRAM_HEADER) {
bcm47xxpart_add_part(&parts[curr_part++], "nvram",
master->size - blocksize, 0);
break;
}
}
kfree(buf);
/*

View File

@ -1523,6 +1523,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
oobreadlen -= toread;
}
}
if (chip->options & NAND_NEED_READRDY) {
/* Apply delay or wait for ready/busy pin */
if (!chip->dev_ready)
udelay(chip->chip_delay);
else
nand_wait_ready(mtd);
}
} else {
memcpy(buf, chip->buffers->databuf + col, bytes);
buf += bytes;
@ -1787,6 +1795,14 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
len = min(len, readlen);
buf = nand_transfer_oob(chip, buf, ops, len);
if (chip->options & NAND_NEED_READRDY) {
/* Apply delay or wait for ready/busy pin */
if (!chip->dev_ready)
udelay(chip->chip_delay);
else
nand_wait_ready(mtd);
}
readlen -= len;
if (!readlen)
break;

View File

@ -22,49 +22,51 @@
* 512 512 Byte page size
*/
struct nand_flash_dev nand_flash_ids[] = {
#define SP_OPTIONS NAND_NEED_READRDY
#define SP_OPTIONS16 (SP_OPTIONS | NAND_BUSWIDTH_16)
#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, SP_OPTIONS},
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, SP_OPTIONS},
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, SP_OPTIONS},
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, SP_OPTIONS},
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, SP_OPTIONS},
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, SP_OPTIONS},
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, SP_OPTIONS},
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, SP_OPTIONS},
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, SP_OPTIONS},
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, SP_OPTIONS},
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, SP_OPTIONS},
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, SP_OPTIONS},
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, SP_OPTIONS16},
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, SP_OPTIONS16},
#endif
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, SP_OPTIONS},
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, SP_OPTIONS},
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, SP_OPTIONS16},
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, SP_OPTIONS16},
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, SP_OPTIONS},
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, SP_OPTIONS},
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, SP_OPTIONS16},
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, SP_OPTIONS16},
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, SP_OPTIONS},
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, SP_OPTIONS},
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, SP_OPTIONS16},
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, SP_OPTIONS16},
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, SP_OPTIONS},
{"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, SP_OPTIONS},
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, SP_OPTIONS},
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, SP_OPTIONS16},
{"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, SP_OPTIONS16},
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, SP_OPTIONS16},
{"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, SP_OPTIONS16},
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, SP_OPTIONS},
/*
* These are the new chips with large page size. The pagesize and the

View File

@ -187,6 +187,13 @@ typedef enum {
* This happens with the Renesas AG-AND chips, possibly others.
*/
#define BBT_AUTO_REFRESH 0x00000080
/*
* Chip requires ready check on read (for auto-incremented sequential read).
* True only for small page devices; large page devices do not support
* autoincrement.
*/
#define NAND_NEED_READRDY 0x00000100
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE 0x00000200