MTD fixes for 4.2
JFFS2
* fix a theoretical unbalanced locking issue; the lock handling was a bit
unclean, but AFAICT, it didn't actually lead to real deadlocks
NAND
* brcmnand driver: new driver supporting NAND controller found originally on
Broadcom STB SoCs (BCM7xxx), but now also found on BCM63xxx, iProc (e.g.,
Cygnus, BCM5301x), BCM3xxx, and more
* Begin factoring out BBT code so it can be shared between traditional
(parallel) NAND drivers and upcoming SPI NAND drivers (WIP)
* Add common DT-based init support, so nand_base can pick up some flash
properties automatically, using established common NAND DT properties
* mxc_nand: support 8-bit ECC
* pxa3xx_nand:
- fix build for ARM64
- use a jiffies-based timeout
SPI NOR
* Add a few new IDs
* Clear out some unnecessary entries
* Make sure SECT_4K flags are correct for all (?) entries
Core
* Fix mtd->usecount race conditions (BUG_ON())
* Switch to modern PM ops
Other
* CFI: save code space by de-inlining large functions
* Clean up some partition parser selection code across several drivers
* Various miscellaneous changes, mostly minor
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJViZdKAAoJEFySrpd9RFgtaqoQAINkYUdxa8mOlmXQSIhWz19K
5FJqJN+/lgrYmIGI1SzVy/TTB/V4hWH+9h1snU98ToaHFACqbKKeo6FLs6GRd+WJ
adR9H4PUjtAZOt8trKzzygJnqvRPDWnn6H+0urxFv7kpyPTEorifiiI6+o3AM995
vh+YsLJNFYHucIzi4TVkgwssLYi8I9TOb35pDnW2uT/ikDi+4Uu+Ocq6u7SuMPXV
Zch6DcmBhtTQ9ghBwF/dMMAhyyMLyY4q0+CEzmJGxNU+g2o1njOTUDBv+lLqxxMB
fUXMAPXIT3ndhWjMmzklG7AjOorbg44aG2UlqJWXx00VYJKNf+pljpgdHOXKiuWo
xYkqOYnEM8gZ4qYNInKbbv34Q2+EjCxg+aAWxh+yRCJrfnF3p5/QSMVL2P2JNrc3
Kg8W7pW42xOeGxTYpydBtvpq+41qRtdWMgNp47PHvKF0mhpeSCCvRf/YfU4cNcfv
WfQzBLy/d7RMVFyvACdvzerF/fh9YX3yxV0B0LstytCSZO13617F6HHpm1pYfP0v
d9GpLpdiFktoG/AXpPzlSl992ALf0SQaedamuxApfvLVymDkG9xoO0P5p6SbOiJ0
QnBvEMkswEf7ExPzr5SYufSE93wikAEsAfjsLOHo+FQQ57eaRgpCOZHHgfuwcTra
xUr6u2Rq9iDenhVYDqJU
=JN5N
-----END PGP SIGNATURE-----
Merge tag 'for-linus-20150623' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"JFFS2:
- fix a theoretical unbalanced locking issue; the lock handling was a
bit unclean, but AFAICT, it didn't actually lead to real deadlocks
NAND:
- brcmnand driver: new driver supporting NAND controller found
originally on Broadcom STB SoCs (BCM7xxx), but now also found on
BCM63xxx, iProc (e.g., Cygnus, BCM5301x), BCM3xxx, and more
- begin factoring out BBT code so it can be shared between
traditional (parallel) NAND drivers and upcoming SPI NAND drivers
(WIP)
- add common DT-based init support, so nand_base can pick up some
flash properties automatically, using established common NAND DT
properties
- mxc_nand: support 8-bit ECC
- pxa3xx_nand:
* fix build for ARM64
* use a jiffies-based timeout
SPI NOR:
- add a few new IDs
- clear out some unnecessary entries
- make sure SECT_4K flags are correct for all (?) entries
Core:
- fix mtd->usecount race conditions (BUG_ON())
- switch to modern PM ops
Other:
- CFI: save code space by de-inlining large functions
- clean up some partition parser selection code across several
drivers
- various miscellaneous changes, mostly minor"
* tag 'for-linus-20150623' of git://git.infradead.org/linux-mtd: (57 commits)
mtd: docg3: Fix kasprintf() usage
mtd: docg3: Don't leak docg3->bbt in error path
mtd: nandsim: Fix kasprintf() usage
mtd: cs553x_nand: Fix kasprintf() usage
mtd: r852: Fix device_create_file() usage
mtd: brcmnand: drop unnecessary initialization
mtd: propagate error codes from add_mtd_device()
mtd: diskonchip: remove two-phase partitioning / registration
mtd: dc21285: use raw spinlock functions for nw_gpio_lock
mtd: chips: fixup dependencies, to prevent build error
mtd: cfi_cmdset_0002: Initialize datum before calling map_word_load_partial
mtd: cfi: deinline large functions
mtd: lantiq-flash: use default partition parsers
mtd: plat_nand: use default partition probe
mtd: nand: correct indentation within conditional
mtd: remove incorrect file name
mtd: blktrans: use better error code for unimplemented ioctl()
mtd: maps: Spelling s/reseved/reserved/
mtd: blktrans: change blktrans_getgeo return value
mtd: mxc_nand: generate nand_ecclayout for 8 bit ECC
...
This commit is contained in:
commit
54245ed870
47 changed files with 3329 additions and 394 deletions
|
|
@ -296,183 +296,19 @@ struct cfi_private {
|
|||
struct flchip chips[0]; /* per-chip data structure for each chip */
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the command address according to the given geometry.
|
||||
*/
|
||||
static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs,
|
||||
struct map_info *map, struct cfi_private *cfi)
|
||||
{
|
||||
unsigned bankwidth = map_bankwidth(map);
|
||||
unsigned interleave = cfi_interleave(cfi);
|
||||
unsigned type = cfi->device_type;
|
||||
uint32_t addr;
|
||||
|
||||
addr = (cmd_ofs * type) * interleave;
|
||||
uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs,
|
||||
struct map_info *map, struct cfi_private *cfi);
|
||||
|
||||
/* Modify the unlock address if we are in compatibility mode.
|
||||
* For 16bit devices on 8 bit busses
|
||||
* and 32bit devices on 16 bit busses
|
||||
* set the low bit of the alternating bit sequence of the address.
|
||||
*/
|
||||
if (((type * interleave) > bankwidth) && ((cmd_ofs & 0xff) == 0xaa))
|
||||
addr |= (type >> 1)*interleave;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transforms the CFI command for the given geometry (bus width & interleave).
|
||||
* It looks too long to be inline, but in the common case it should almost all
|
||||
* get optimised away.
|
||||
*/
|
||||
static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
|
||||
{
|
||||
map_word val = { {0} };
|
||||
int wordwidth, words_per_bus, chip_mode, chips_per_word;
|
||||
unsigned long onecmd;
|
||||
int i;
|
||||
|
||||
/* We do it this way to give the compiler a fighting chance
|
||||
of optimising away all the crap for 'bankwidth' larger than
|
||||
an unsigned long, in the common case where that support is
|
||||
disabled */
|
||||
if (map_bankwidth_is_large(map)) {
|
||||
wordwidth = sizeof(unsigned long);
|
||||
words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
|
||||
} else {
|
||||
wordwidth = map_bankwidth(map);
|
||||
words_per_bus = 1;
|
||||
}
|
||||
|
||||
chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
|
||||
chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
|
||||
|
||||
/* First, determine what the bit-pattern should be for a single
|
||||
device, according to chip mode and endianness... */
|
||||
switch (chip_mode) {
|
||||
default: BUG();
|
||||
case 1:
|
||||
onecmd = cmd;
|
||||
break;
|
||||
case 2:
|
||||
onecmd = cpu_to_cfi16(map, cmd);
|
||||
break;
|
||||
case 4:
|
||||
onecmd = cpu_to_cfi32(map, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now replicate it across the size of an unsigned long, or
|
||||
just to the bus width as appropriate */
|
||||
switch (chips_per_word) {
|
||||
default: BUG();
|
||||
#if BITS_PER_LONG >= 64
|
||||
case 8:
|
||||
onecmd |= (onecmd << (chip_mode * 32));
|
||||
#endif
|
||||
case 4:
|
||||
onecmd |= (onecmd << (chip_mode * 16));
|
||||
case 2:
|
||||
onecmd |= (onecmd << (chip_mode * 8));
|
||||
case 1:
|
||||
;
|
||||
}
|
||||
|
||||
/* And finally, for the multi-word case, replicate it
|
||||
in all words in the structure */
|
||||
for (i=0; i < words_per_bus; i++) {
|
||||
val.x[i] = onecmd;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi);
|
||||
#define CMD(x) cfi_build_cmd((x), map, cfi)
|
||||
|
||||
|
||||
static inline unsigned long cfi_merge_status(map_word val, struct map_info *map,
|
||||
struct cfi_private *cfi)
|
||||
{
|
||||
int wordwidth, words_per_bus, chip_mode, chips_per_word;
|
||||
unsigned long onestat, res = 0;
|
||||
int i;
|
||||
|
||||
/* We do it this way to give the compiler a fighting chance
|
||||
of optimising away all the crap for 'bankwidth' larger than
|
||||
an unsigned long, in the common case where that support is
|
||||
disabled */
|
||||
if (map_bankwidth_is_large(map)) {
|
||||
wordwidth = sizeof(unsigned long);
|
||||
words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1
|
||||
} else {
|
||||
wordwidth = map_bankwidth(map);
|
||||
words_per_bus = 1;
|
||||
}
|
||||
|
||||
chip_mode = map_bankwidth(map) / cfi_interleave(cfi);
|
||||
chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map);
|
||||
|
||||
onestat = val.x[0];
|
||||
/* Or all status words together */
|
||||
for (i=1; i < words_per_bus; i++) {
|
||||
onestat |= val.x[i];
|
||||
}
|
||||
|
||||
res = onestat;
|
||||
switch(chips_per_word) {
|
||||
default: BUG();
|
||||
#if BITS_PER_LONG >= 64
|
||||
case 8:
|
||||
res |= (onestat >> (chip_mode * 32));
|
||||
#endif
|
||||
case 4:
|
||||
res |= (onestat >> (chip_mode * 16));
|
||||
case 2:
|
||||
res |= (onestat >> (chip_mode * 8));
|
||||
case 1:
|
||||
;
|
||||
}
|
||||
|
||||
/* Last, determine what the bit-pattern should be for a single
|
||||
device, according to chip mode and endianness... */
|
||||
switch (chip_mode) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
res = cfi16_to_cpu(map, res);
|
||||
break;
|
||||
case 4:
|
||||
res = cfi32_to_cpu(map, res);
|
||||
break;
|
||||
default: BUG();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned long cfi_merge_status(map_word val, struct map_info *map,
|
||||
struct cfi_private *cfi);
|
||||
#define MERGESTATUS(x) cfi_merge_status((x), map, cfi)
|
||||
|
||||
|
||||
/*
|
||||
* Sends a CFI command to a bank of flash for the given geometry.
|
||||
*
|
||||
* Returns the offset in flash where the command was written.
|
||||
* If prev_val is non-null, it will be set to the value at the command address,
|
||||
* before the command was written.
|
||||
*/
|
||||
static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
|
||||
uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base,
|
||||
struct map_info *map, struct cfi_private *cfi,
|
||||
int type, map_word *prev_val)
|
||||
{
|
||||
map_word val;
|
||||
uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi);
|
||||
val = cfi_build_cmd(cmd, map, cfi);
|
||||
|
||||
if (prev_val)
|
||||
*prev_val = map_read(map, addr);
|
||||
|
||||
map_write(map, val, addr);
|
||||
|
||||
return addr - base;
|
||||
}
|
||||
int type, map_word *prev_val);
|
||||
|
||||
static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr)
|
||||
{
|
||||
|
|
@ -506,15 +342,7 @@ static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void cfi_udelay(int us)
|
||||
{
|
||||
if (us >= 1000) {
|
||||
msleep((us+999)/1000);
|
||||
} else {
|
||||
udelay(us);
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
void cfi_udelay(int us);
|
||||
|
||||
int __xipram cfi_qry_present(struct map_info *map, __u32 base,
|
||||
struct cfi_private *cfi);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
struct mtd_info;
|
||||
struct nand_flash_dev;
|
||||
struct device_node;
|
||||
|
||||
/* Scan and identify a NAND device */
|
||||
extern int nand_scan(struct mtd_info *mtd, int max_chips);
|
||||
/*
|
||||
|
|
@ -542,6 +544,7 @@ struct nand_buffers {
|
|||
* flash device
|
||||
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
|
||||
* flash device.
|
||||
* @dn: [BOARDSPECIFIC] device node describing this instance
|
||||
* @read_byte: [REPLACEABLE] read one byte from the chip
|
||||
* @read_word: [REPLACEABLE] read one word from the chip
|
||||
* @write_byte: [REPLACEABLE] write a single byte to the chip on the
|
||||
|
|
@ -644,6 +647,8 @@ struct nand_chip {
|
|||
void __iomem *IO_ADDR_R;
|
||||
void __iomem *IO_ADDR_W;
|
||||
|
||||
struct device_node *dn;
|
||||
|
||||
uint8_t (*read_byte)(struct mtd_info *mtd);
|
||||
u16 (*read_word)(struct mtd_info *mtd);
|
||||
void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
|
||||
|
|
@ -833,7 +838,6 @@ struct nand_manufacturers {
|
|||
extern struct nand_flash_dev nand_flash_ids[];
|
||||
extern struct nand_manufacturers nand_manuf_ids[];
|
||||
|
||||
extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
|
||||
extern int nand_default_bbt(struct mtd_info *mtd);
|
||||
extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
|
||||
extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue