diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 15:00:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 15:00:44 -0400 |
| commit | a62d016cece2fce1d5e4eedf36b17f03a7a5c78e (patch) | |
| tree | ac37b4835be5f4fe0e04611fdb40c85abb98ec78 /include/linux | |
| parent | 7c034dfd58bbc056280262887acf5b7a98944d0a (diff) | |
| parent | 3e550d2396d9deef77328237ed992e19dcfefca5 (diff) | |
Merge tag 'for-linus-20150422' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"Common MTD:
- Add Kconfig option for keeping both the 'master' and 'partition'
MTDs registered as devices. This would really make a better
default if we could do it over, as it allows a lot more flexibility
in (1) determining the flash topology of the system from user-space
and (2) adding temporary partitions at runtime (ioctl(BLKPG)).
Unfortunately, this would possibly cause user-space breakage, as it
will cause renumbering of the /dev/mtdX devices. We'll see if we
can change this in the future, as there have already been a few
people looking for this feature, and I know others have just been
working around our current limitations instead of fixing them this
way.
- Along with the previous change, add some additional information to
sysfs, so user-space can read the offset of each partition within
its master device
SPI NOR:
- add new device tree compatible binding to represent the
mostly-compatible class of SPI NOR flash which can be detected by
their extended JEDEC ID bytes, cutting down the duplication of our
ID tables
- misc. new IDs
Various other miscellaneous fixes and changes"
* tag 'for-linus-20150422' of git://git.infradead.org/linux-mtd: (53 commits)
mtd: spi-nor: Add support for Macronix mx25u6435f serial flash
mtd: spi-nor: Add support for Winbond w25q64dw serial flash
mtd: spi-nor: add support for the Winbond W25X05 flash
mtd: spi-nor: support en25s64 device
mtd: m25p80: bind to "nor-jedec" ID, for auto-detection
Documentation: devicetree: m25p80: add "nor-jedec" binding
mtd: Make MTD tests cancelable
mtd: mtd_oobtest: Fix bitflip_limit usage in test case 3
mtd: docg3: remove invalid __exit annotations
mtd: fsl_ifc_nand: use msecs_to_jiffies for time conversion
mtd: atmel_nand: don't map the ROM table if no pmecc table offset in DT
mtd: atmel_nand: add a definition for the oob reserved bytes
mtd: part: Remove partition overlap checks
mtd: part: Add sysfs variable for offset of partition
mtd: part: Create the master device node when partitioned
mtd: ts5500_flash: Fix typo in MODULE_DESCRIPTION in ts5500_flash.c
mtd: denali: Disable sub-page writes in Denali NAND driver
mtd: pxa3xx_nand: cleanup wait_for_completion handling
mtd: nand: gpmi: Check for scan_bbt() error
mtd: nand: gpmi: fixup return type of wait_for_completion_timeout
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/mtd/map.h | 54 | ||||
| -rw-r--r-- | include/linux/mtd/spi-nor.h | 5 |
2 files changed, 40 insertions, 19 deletions
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 5f487d776411..29975c73a953 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h | |||
| @@ -77,7 +77,7 @@ | |||
| 77 | /* ensure we never evaluate anything shorted than an unsigned long | 77 | /* ensure we never evaluate anything shorted than an unsigned long |
| 78 | * to zero, and ensure we'll never miss the end of an comparison (bjd) */ | 78 | * to zero, and ensure we'll never miss the end of an comparison (bjd) */ |
| 79 | 79 | ||
| 80 | #define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long)) | 80 | #define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long)) |
| 81 | 81 | ||
| 82 | #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 | 82 | #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8 |
| 83 | # ifdef map_bankwidth | 83 | # ifdef map_bankwidth |
| @@ -181,7 +181,7 @@ static inline int map_bankwidth_supported(int w) | |||
| 181 | } | 181 | } |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | #define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG ) | 184 | #define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG) |
| 185 | 185 | ||
| 186 | typedef union { | 186 | typedef union { |
| 187 | unsigned long x[MAX_MAP_LONGS]; | 187 | unsigned long x[MAX_MAP_LONGS]; |
| @@ -264,20 +264,22 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *); | |||
| 264 | struct mtd_info *do_map_probe(const char *name, struct map_info *map); | 264 | struct mtd_info *do_map_probe(const char *name, struct map_info *map); |
| 265 | void map_destroy(struct mtd_info *mtd); | 265 | void map_destroy(struct mtd_info *mtd); |
| 266 | 266 | ||
| 267 | #define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0) | 267 | #define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0) |
| 268 | #define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0) | 268 | #define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0) |
| 269 | 269 | ||
| 270 | #define INVALIDATE_CACHED_RANGE(map, from, size) \ | 270 | #define INVALIDATE_CACHED_RANGE(map, from, size) \ |
| 271 | do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0) | 271 | do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0) |
| 272 | 272 | ||
| 273 | 273 | ||
| 274 | static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2) | 274 | static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2) |
| 275 | { | 275 | { |
| 276 | int i; | 276 | int i; |
| 277 | for (i=0; i<map_words(map); i++) { | 277 | |
| 278 | for (i = 0; i < map_words(map); i++) { | ||
| 278 | if (val1.x[i] != val2.x[i]) | 279 | if (val1.x[i] != val2.x[i]) |
| 279 | return 0; | 280 | return 0; |
| 280 | } | 281 | } |
| 282 | |||
| 281 | return 1; | 283 | return 1; |
| 282 | } | 284 | } |
| 283 | 285 | ||
| @@ -286,9 +288,9 @@ static inline map_word map_word_and(struct map_info *map, map_word val1, map_wor | |||
| 286 | map_word r; | 288 | map_word r; |
| 287 | int i; | 289 | int i; |
| 288 | 290 | ||
| 289 | for (i=0; i<map_words(map); i++) { | 291 | for (i = 0; i < map_words(map); i++) |
| 290 | r.x[i] = val1.x[i] & val2.x[i]; | 292 | r.x[i] = val1.x[i] & val2.x[i]; |
| 291 | } | 293 | |
| 292 | return r; | 294 | return r; |
| 293 | } | 295 | } |
| 294 | 296 | ||
| @@ -297,9 +299,9 @@ static inline map_word map_word_clr(struct map_info *map, map_word val1, map_wor | |||
| 297 | map_word r; | 299 | map_word r; |
| 298 | int i; | 300 | int i; |
| 299 | 301 | ||
| 300 | for (i=0; i<map_words(map); i++) { | 302 | for (i = 0; i < map_words(map); i++) |
| 301 | r.x[i] = val1.x[i] & ~val2.x[i]; | 303 | r.x[i] = val1.x[i] & ~val2.x[i]; |
| 302 | } | 304 | |
| 303 | return r; | 305 | return r; |
| 304 | } | 306 | } |
| 305 | 307 | ||
| @@ -308,22 +310,33 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word | |||
| 308 | map_word r; | 310 | map_word r; |
| 309 | int i; | 311 | int i; |
| 310 | 312 | ||
| 311 | for (i=0; i<map_words(map); i++) { | 313 | for (i = 0; i < map_words(map); i++) |
| 312 | r.x[i] = val1.x[i] | val2.x[i]; | 314 | r.x[i] = val1.x[i] | val2.x[i]; |
| 313 | } | 315 | |
| 314 | return r; | 316 | return r; |
| 315 | } | 317 | } |
| 316 | 318 | ||
| 317 | #define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b)) | 319 | static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) |
| 320 | { | ||
| 321 | int i; | ||
| 322 | |||
| 323 | for (i = 0; i < map_words(map); i++) { | ||
| 324 | if ((val1.x[i] & val2.x[i]) != val3.x[i]) | ||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | return 1; | ||
| 329 | } | ||
| 318 | 330 | ||
| 319 | static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) | 331 | static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) |
| 320 | { | 332 | { |
| 321 | int i; | 333 | int i; |
| 322 | 334 | ||
| 323 | for (i=0; i<map_words(map); i++) { | 335 | for (i = 0; i < map_words(map); i++) { |
| 324 | if (val1.x[i] & val2.x[i]) | 336 | if (val1.x[i] & val2.x[i]) |
| 325 | return 1; | 337 | return 1; |
| 326 | } | 338 | } |
| 339 | |||
| 327 | return 0; | 340 | return 0; |
| 328 | } | 341 | } |
| 329 | 342 | ||
| @@ -355,14 +368,16 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig | |||
| 355 | 368 | ||
| 356 | if (map_bankwidth_is_large(map)) { | 369 | if (map_bankwidth_is_large(map)) { |
| 357 | char *dest = (char *)&orig; | 370 | char *dest = (char *)&orig; |
| 371 | |||
| 358 | memcpy(dest+start, buf, len); | 372 | memcpy(dest+start, buf, len); |
| 359 | } else { | 373 | } else { |
| 360 | for (i=start; i < start+len; i++) { | 374 | for (i = start; i < start+len; i++) { |
| 361 | int bitpos; | 375 | int bitpos; |
| 376 | |||
| 362 | #ifdef __LITTLE_ENDIAN | 377 | #ifdef __LITTLE_ENDIAN |
| 363 | bitpos = i*8; | 378 | bitpos = i * 8; |
| 364 | #else /* __BIG_ENDIAN */ | 379 | #else /* __BIG_ENDIAN */ |
| 365 | bitpos = (map_bankwidth(map)-1-i)*8; | 380 | bitpos = (map_bankwidth(map) - 1 - i) * 8; |
| 366 | #endif | 381 | #endif |
| 367 | orig.x[0] &= ~(0xff << bitpos); | 382 | orig.x[0] &= ~(0xff << bitpos); |
| 368 | orig.x[0] |= (unsigned long)buf[i-start] << bitpos; | 383 | orig.x[0] |= (unsigned long)buf[i-start] << bitpos; |
| @@ -384,9 +399,10 @@ static inline map_word map_word_ff(struct map_info *map) | |||
| 384 | 399 | ||
| 385 | if (map_bankwidth(map) < MAP_FF_LIMIT) { | 400 | if (map_bankwidth(map) < MAP_FF_LIMIT) { |
| 386 | int bw = 8 * map_bankwidth(map); | 401 | int bw = 8 * map_bankwidth(map); |
| 402 | |||
| 387 | r.x[0] = (1UL << bw) - 1; | 403 | r.x[0] = (1UL << bw) - 1; |
| 388 | } else { | 404 | } else { |
| 389 | for (i=0; i<map_words(map); i++) | 405 | for (i = 0; i < map_words(map); i++) |
| 390 | r.x[i] = ~0UL; | 406 | r.x[i] = ~0UL; |
| 391 | } | 407 | } |
| 392 | return r; | 408 | return r; |
| @@ -407,7 +423,7 @@ static inline map_word inline_map_read(struct map_info *map, unsigned long ofs) | |||
| 407 | r.x[0] = __raw_readq(map->virt + ofs); | 423 | r.x[0] = __raw_readq(map->virt + ofs); |
| 408 | #endif | 424 | #endif |
| 409 | else if (map_bankwidth_is_large(map)) | 425 | else if (map_bankwidth_is_large(map)) |
| 410 | memcpy_fromio(r.x, map->virt+ofs, map->bankwidth); | 426 | memcpy_fromio(r.x, map->virt + ofs, map->bankwidth); |
| 411 | else | 427 | else |
| 412 | BUG(); | 428 | BUG(); |
| 413 | 429 | ||
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4720b86ee73d..e5409524bb0a 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
| @@ -155,6 +155,8 @@ enum spi_nor_option_flags { | |||
| 155 | * @write: [DRIVER-SPECIFIC] write data to the SPI NOR | 155 | * @write: [DRIVER-SPECIFIC] write data to the SPI NOR |
| 156 | * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR | 156 | * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR |
| 157 | * at the offset @offs | 157 | * at the offset @offs |
| 158 | * @lock: [FLASH-SPECIFIC] lock a region of the SPI NOR | ||
| 159 | * @unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR | ||
| 158 | * @priv: the private data | 160 | * @priv: the private data |
| 159 | */ | 161 | */ |
| 160 | struct spi_nor { | 162 | struct spi_nor { |
| @@ -189,6 +191,9 @@ struct spi_nor { | |||
| 189 | size_t len, size_t *retlen, const u_char *write_buf); | 191 | size_t len, size_t *retlen, const u_char *write_buf); |
| 190 | int (*erase)(struct spi_nor *nor, loff_t offs); | 192 | int (*erase)(struct spi_nor *nor, loff_t offs); |
| 191 | 193 | ||
| 194 | int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | ||
| 195 | int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); | ||
| 196 | |||
| 192 | void *priv; | 197 | void *priv; |
| 193 | }; | 198 | }; |
| 194 | 199 | ||
