diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-08 21:13:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-08 21:13:21 -0400 |
commit | c309bfa9b481e7dbd3e1ab819271bf3009f44859 (patch) | |
tree | fc102360b3e7cb53796a451bc8fe01239c734e07 | |
parent | 9e9ac896667a55ae9a3df119611ee5322abe2890 (diff) | |
parent | 2a500afe1e0e84c7a126df693dbd01353756dcfa (diff) |
Merge tag 'for-linus-20140808' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"AMD-compatible CFI driver:
- Support OTP programming for Micron M29EW family
- Increase buffer write timeout, according to detected flash
parameter info
NAND
- Add helpers for retrieving ONFI timing modes
- GPMI: provide option to disable bad block marker swapping (required
for Ka-On electronics platforms)
SPI NOR
- EON EN25QH128 support
- Support new Flag Status Register (FSR) on a few Micron flash
Common
- New sysfs entries for bad block and ECC stats
And a few miscellaneous refactorings, cleanups, and driver
improvements"
* tag 'for-linus-20140808' of git://git.infradead.org/linux-mtd: (31 commits)
mtd: gpmi: make blockmark swapping optional
mtd: gpmi: remove line breaks from error messages and improve wording
mtd: gpmi: remove useless (void *) type casts and spaces between type casts and variables
mtd: atmel_nand: NFC: support multiple interrupt handling
mtd: atmel_nand: implement the nfc_device_ready() by checking the R/B bit
mtd: atmel_nand: add NFC status error check
mtd: atmel_nand: make ecc parameters same as definition
mtd: nand: add ONFI timing mode to nand_timings converter
mtd: nand: define struct nand_timings
mtd: cfi_cmdset_0002: fix do_write_buffer() timeout error
mtd: denali: use 8 bytes for READID command
mtd/ftl: fix the double free of the buffers allocated in build_maps()
mtd: phram: Fix whitespace issues
mtd: spi-nor: add support for EON EN25QH128
mtd: cfi_cmdset_0002: Add support for locking OTP memory
mtd: cfi_cmdset_0002: Add support for writing OTP memory
mtd: cfi_cmdset_0002: Invalidate cache after entering/exiting OTP memory
mtd: cfi_cmdset_0002: Add support for reading OTP
mtd: spi-nor: add support for flag status register on Micron chips
mtd: Account for BBT blocks when a partition is being allocated
...
27 files changed, 1032 insertions, 146 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd index 1399bb2da3eb..76ee192f80a0 100644 --- a/Documentation/ABI/testing/sysfs-class-mtd +++ b/Documentation/ABI/testing/sysfs-class-mtd | |||
@@ -184,3 +184,41 @@ Description: | |||
184 | 184 | ||
185 | It will always be a non-negative integer. In the case of | 185 | It will always be a non-negative integer. In the case of |
186 | devices lacking any ECC capability, it is 0. | 186 | devices lacking any ECC capability, it is 0. |
187 | |||
188 | What: /sys/class/mtd/mtdX/ecc_failures | ||
189 | Date: June 2014 | ||
190 | KernelVersion: 3.17 | ||
191 | Contact: linux-mtd@lists.infradead.org | ||
192 | Description: | ||
193 | The number of failures reported by this device's ECC. Typically, | ||
194 | these failures are associated with failed read operations. | ||
195 | |||
196 | It will always be a non-negative integer. In the case of | ||
197 | devices lacking any ECC capability, it is 0. | ||
198 | |||
199 | What: /sys/class/mtd/mtdX/corrected_bits | ||
200 | Date: June 2014 | ||
201 | KernelVersion: 3.17 | ||
202 | Contact: linux-mtd@lists.infradead.org | ||
203 | Description: | ||
204 | The number of bits that have been corrected by means of the | ||
205 | device's ECC. | ||
206 | |||
207 | It will always be a non-negative integer. In the case of | ||
208 | devices lacking any ECC capability, it is 0. | ||
209 | |||
210 | What: /sys/class/mtd/mtdX/bad_blocks | ||
211 | Date: June 2014 | ||
212 | KernelVersion: 3.17 | ||
213 | Contact: linux-mtd@lists.infradead.org | ||
214 | Description: | ||
215 | The number of blocks marked as bad, if any, in this partition. | ||
216 | |||
217 | What: /sys/class/mtd/mtdX/bbt_blocks | ||
218 | Date: June 2014 | ||
219 | KernelVersion: 3.17 | ||
220 | Contact: linux-mtd@lists.infradead.org | ||
221 | Description: | ||
222 | The number of blocks that are marked as reserved, if any, in | ||
223 | this partition. These are typically used to store the in-flash | ||
224 | bad block table (BBT). | ||
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt index 458d59634688..a011fdf61dbf 100644 --- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt | |||
@@ -25,6 +25,16 @@ Optional properties: | |||
25 | discoverable or this property is not enabled, | 25 | discoverable or this property is not enabled, |
26 | the software may chooses an implementation-defined | 26 | the software may chooses an implementation-defined |
27 | ECC scheme. | 27 | ECC scheme. |
28 | - fsl,no-blockmark-swap: Don't swap the bad block marker from the OOB | ||
29 | area with the byte in the data area but rely on the | ||
30 | flash based BBT for identifying bad blocks. | ||
31 | NOTE: this is only valid in conjunction with | ||
32 | 'nand-on-flash-bbt'. | ||
33 | WARNING: on i.MX28 blockmark swapping cannot be | ||
34 | disabled for the BootROM in the FCB. Thus, | ||
35 | partitions written from Linux with this feature | ||
36 | turned on may not be accessible by the BootROM | ||
37 | code. | ||
28 | 38 | ||
29 | The device tree may optionally contain sub-nodes describing partitions of the | 39 | The device tree may optionally contain sub-nodes describing partitions of the |
30 | address space. See partition.txt for more detail. | 40 | address space. See partition.txt for more detail. |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e21fde9d4d7e..5a4bfe33112a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -58,7 +58,18 @@ static void cfi_amdstd_sync (struct mtd_info *); | |||
58 | static int cfi_amdstd_suspend (struct mtd_info *); | 58 | static int cfi_amdstd_suspend (struct mtd_info *); |
59 | static void cfi_amdstd_resume (struct mtd_info *); | 59 | static void cfi_amdstd_resume (struct mtd_info *); |
60 | static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *); | 60 | static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *); |
61 | static int cfi_amdstd_get_fact_prot_info(struct mtd_info *, size_t, | ||
62 | size_t *, struct otp_info *); | ||
63 | static int cfi_amdstd_get_user_prot_info(struct mtd_info *, size_t, | ||
64 | size_t *, struct otp_info *); | ||
61 | static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 65 | static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
66 | static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *, loff_t, size_t, | ||
67 | size_t *, u_char *); | ||
68 | static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t, | ||
69 | size_t *, u_char *); | ||
70 | static int cfi_amdstd_write_user_prot_reg(struct mtd_info *, loff_t, size_t, | ||
71 | size_t *, u_char *); | ||
72 | static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *, loff_t, size_t); | ||
62 | 73 | ||
63 | static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | 74 | static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, |
64 | size_t *retlen, const u_char *buf); | 75 | size_t *retlen, const u_char *buf); |
@@ -518,6 +529,12 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
518 | mtd->_sync = cfi_amdstd_sync; | 529 | mtd->_sync = cfi_amdstd_sync; |
519 | mtd->_suspend = cfi_amdstd_suspend; | 530 | mtd->_suspend = cfi_amdstd_suspend; |
520 | mtd->_resume = cfi_amdstd_resume; | 531 | mtd->_resume = cfi_amdstd_resume; |
532 | mtd->_read_user_prot_reg = cfi_amdstd_read_user_prot_reg; | ||
533 | mtd->_read_fact_prot_reg = cfi_amdstd_read_fact_prot_reg; | ||
534 | mtd->_get_fact_prot_info = cfi_amdstd_get_fact_prot_info; | ||
535 | mtd->_get_user_prot_info = cfi_amdstd_get_user_prot_info; | ||
536 | mtd->_write_user_prot_reg = cfi_amdstd_write_user_prot_reg; | ||
537 | mtd->_lock_user_prot_reg = cfi_amdstd_lock_user_prot_reg; | ||
521 | mtd->flags = MTD_CAP_NORFLASH; | 538 | mtd->flags = MTD_CAP_NORFLASH; |
522 | mtd->name = map->name; | 539 | mtd->name = map->name; |
523 | mtd->writesize = 1; | 540 | mtd->writesize = 1; |
@@ -628,6 +645,23 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
628 | cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp; | 645 | cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp; |
629 | cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp; | 646 | cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp; |
630 | cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp; | 647 | cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp; |
648 | /* | ||
649 | * First calculate the timeout max according to timeout field | ||
650 | * of struct cfi_ident that probed from chip's CFI aera, if | ||
651 | * available. Specify a minimum of 2000us, in case the CFI data | ||
652 | * is wrong. | ||
653 | */ | ||
654 | if (cfi->cfiq->BufWriteTimeoutTyp && | ||
655 | cfi->cfiq->BufWriteTimeoutMax) | ||
656 | cfi->chips[i].buffer_write_time_max = | ||
657 | 1 << (cfi->cfiq->BufWriteTimeoutTyp + | ||
658 | cfi->cfiq->BufWriteTimeoutMax); | ||
659 | else | ||
660 | cfi->chips[i].buffer_write_time_max = 0; | ||
661 | |||
662 | cfi->chips[i].buffer_write_time_max = | ||
663 | max(cfi->chips[i].buffer_write_time_max, 2000); | ||
664 | |||
631 | cfi->chips[i].ref_point_counter = 0; | 665 | cfi->chips[i].ref_point_counter = 0; |
632 | init_waitqueue_head(&(cfi->chips[i].wq)); | 666 | init_waitqueue_head(&(cfi->chips[i].wq)); |
633 | } | 667 | } |
@@ -1137,12 +1171,48 @@ static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_ | |||
1137 | return ret; | 1171 | return ret; |
1138 | } | 1172 | } |
1139 | 1173 | ||
1174 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, | ||
1175 | loff_t adr, size_t len, u_char *buf, size_t grouplen); | ||
1176 | |||
1177 | static inline void otp_enter(struct map_info *map, struct flchip *chip, | ||
1178 | loff_t adr, size_t len) | ||
1179 | { | ||
1180 | struct cfi_private *cfi = map->fldrv_priv; | ||
1181 | |||
1182 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1183 | cfi->device_type, NULL); | ||
1184 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1185 | cfi->device_type, NULL); | ||
1186 | cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, | ||
1187 | cfi->device_type, NULL); | ||
1188 | |||
1189 | INVALIDATE_CACHED_RANGE(map, chip->start + adr, len); | ||
1190 | } | ||
1191 | |||
1192 | static inline void otp_exit(struct map_info *map, struct flchip *chip, | ||
1193 | loff_t adr, size_t len) | ||
1194 | { | ||
1195 | struct cfi_private *cfi = map->fldrv_priv; | ||
1196 | |||
1197 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1198 | cfi->device_type, NULL); | ||
1199 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1200 | cfi->device_type, NULL); | ||
1201 | cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, | ||
1202 | cfi->device_type, NULL); | ||
1203 | cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, | ||
1204 | cfi->device_type, NULL); | ||
1205 | |||
1206 | INVALIDATE_CACHED_RANGE(map, chip->start + adr, len); | ||
1207 | } | ||
1140 | 1208 | ||
1141 | static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) | 1209 | static inline int do_read_secsi_onechip(struct map_info *map, |
1210 | struct flchip *chip, loff_t adr, | ||
1211 | size_t len, u_char *buf, | ||
1212 | size_t grouplen) | ||
1142 | { | 1213 | { |
1143 | DECLARE_WAITQUEUE(wait, current); | 1214 | DECLARE_WAITQUEUE(wait, current); |
1144 | unsigned long timeo = jiffies + HZ; | 1215 | unsigned long timeo = jiffies + HZ; |
1145 | struct cfi_private *cfi = map->fldrv_priv; | ||
1146 | 1216 | ||
1147 | retry: | 1217 | retry: |
1148 | mutex_lock(&chip->mutex); | 1218 | mutex_lock(&chip->mutex); |
@@ -1164,16 +1234,9 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1164 | 1234 | ||
1165 | chip->state = FL_READY; | 1235 | chip->state = FL_READY; |
1166 | 1236 | ||
1167 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1237 | otp_enter(map, chip, adr, len); |
1168 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | ||
1169 | cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1170 | |||
1171 | map_copy_from(map, buf, adr, len); | 1238 | map_copy_from(map, buf, adr, len); |
1172 | 1239 | otp_exit(map, chip, adr, len); | |
1173 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1174 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | ||
1175 | cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1176 | cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1177 | 1240 | ||
1178 | wake_up(&chip->wq); | 1241 | wake_up(&chip->wq); |
1179 | mutex_unlock(&chip->mutex); | 1242 | mutex_unlock(&chip->mutex); |
@@ -1205,7 +1268,8 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
1205 | else | 1268 | else |
1206 | thislen = len; | 1269 | thislen = len; |
1207 | 1270 | ||
1208 | ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); | 1271 | ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, |
1272 | thislen, buf, 0); | ||
1209 | if (ret) | 1273 | if (ret) |
1210 | break; | 1274 | break; |
1211 | 1275 | ||
@@ -1219,8 +1283,267 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
1219 | return ret; | 1283 | return ret; |
1220 | } | 1284 | } |
1221 | 1285 | ||
1286 | static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | ||
1287 | unsigned long adr, map_word datum, | ||
1288 | int mode); | ||
1289 | |||
1290 | static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr, | ||
1291 | size_t len, u_char *buf, size_t grouplen) | ||
1292 | { | ||
1293 | int ret; | ||
1294 | while (len) { | ||
1295 | unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1); | ||
1296 | int gap = adr - bus_ofs; | ||
1297 | int n = min_t(int, len, map_bankwidth(map) - gap); | ||
1298 | map_word datum; | ||
1299 | |||
1300 | if (n != map_bankwidth(map)) { | ||
1301 | /* partial write of a word, load old contents */ | ||
1302 | otp_enter(map, chip, bus_ofs, map_bankwidth(map)); | ||
1303 | datum = map_read(map, bus_ofs); | ||
1304 | otp_exit(map, chip, bus_ofs, map_bankwidth(map)); | ||
1305 | } | ||
1306 | |||
1307 | datum = map_word_load_partial(map, datum, buf, gap, n); | ||
1308 | ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE); | ||
1309 | if (ret) | ||
1310 | return ret; | ||
1311 | |||
1312 | adr += n; | ||
1313 | buf += n; | ||
1314 | len -= n; | ||
1315 | } | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr, | ||
1321 | size_t len, u_char *buf, size_t grouplen) | ||
1322 | { | ||
1323 | struct cfi_private *cfi = map->fldrv_priv; | ||
1324 | uint8_t lockreg; | ||
1325 | unsigned long timeo; | ||
1326 | int ret; | ||
1327 | |||
1328 | /* make sure area matches group boundaries */ | ||
1329 | if ((adr != 0) || (len != grouplen)) | ||
1330 | return -EINVAL; | ||
1331 | |||
1332 | mutex_lock(&chip->mutex); | ||
1333 | ret = get_chip(map, chip, chip->start, FL_LOCKING); | ||
1334 | if (ret) { | ||
1335 | mutex_unlock(&chip->mutex); | ||
1336 | return ret; | ||
1337 | } | ||
1338 | chip->state = FL_LOCKING; | ||
1339 | |||
1340 | /* Enter lock register command */ | ||
1341 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1342 | cfi->device_type, NULL); | ||
1343 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1344 | cfi->device_type, NULL); | ||
1345 | cfi_send_gen_cmd(0x40, cfi->addr_unlock1, chip->start, map, cfi, | ||
1346 | cfi->device_type, NULL); | ||
1347 | |||
1348 | /* read lock register */ | ||
1349 | lockreg = cfi_read_query(map, 0); | ||
1350 | |||
1351 | /* set bit 0 to protect extended memory block */ | ||
1352 | lockreg &= ~0x01; | ||
1353 | |||
1354 | /* set bit 0 to protect extended memory block */ | ||
1355 | /* write lock register */ | ||
1356 | map_write(map, CMD(0xA0), chip->start); | ||
1357 | map_write(map, CMD(lockreg), chip->start); | ||
1358 | |||
1359 | /* wait for chip to become ready */ | ||
1360 | timeo = jiffies + msecs_to_jiffies(2); | ||
1361 | for (;;) { | ||
1362 | if (chip_ready(map, adr)) | ||
1363 | break; | ||
1364 | |||
1365 | if (time_after(jiffies, timeo)) { | ||
1366 | pr_err("Waiting for chip to be ready timed out.\n"); | ||
1367 | ret = -EIO; | ||
1368 | break; | ||
1369 | } | ||
1370 | UDELAY(map, chip, 0, 1); | ||
1371 | } | ||
1372 | |||
1373 | /* exit protection commands */ | ||
1374 | map_write(map, CMD(0x90), chip->start); | ||
1375 | map_write(map, CMD(0x00), chip->start); | ||
1376 | |||
1377 | chip->state = FL_READY; | ||
1378 | put_chip(map, chip, chip->start); | ||
1379 | mutex_unlock(&chip->mutex); | ||
1380 | |||
1381 | return ret; | ||
1382 | } | ||
1383 | |||
1384 | static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len, | ||
1385 | size_t *retlen, u_char *buf, | ||
1386 | otp_op_t action, int user_regs) | ||
1387 | { | ||
1388 | struct map_info *map = mtd->priv; | ||
1389 | struct cfi_private *cfi = map->fldrv_priv; | ||
1390 | int ofs_factor = cfi->interleave * cfi->device_type; | ||
1391 | unsigned long base; | ||
1392 | int chipnum; | ||
1393 | struct flchip *chip; | ||
1394 | uint8_t otp, lockreg; | ||
1395 | int ret; | ||
1396 | |||
1397 | size_t user_size, factory_size, otpsize; | ||
1398 | loff_t user_offset, factory_offset, otpoffset; | ||
1399 | int user_locked = 0, otplocked; | ||
1400 | |||
1401 | *retlen = 0; | ||
1402 | |||
1403 | for (chipnum = 0; chipnum < cfi->numchips; chipnum++) { | ||
1404 | chip = &cfi->chips[chipnum]; | ||
1405 | factory_size = 0; | ||
1406 | user_size = 0; | ||
1222 | 1407 | ||
1223 | static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum) | 1408 | /* Micron M29EW family */ |
1409 | if (is_m29ew(cfi)) { | ||
1410 | base = chip->start; | ||
1411 | |||
1412 | /* check whether secsi area is factory locked | ||
1413 | or user lockable */ | ||
1414 | mutex_lock(&chip->mutex); | ||
1415 | ret = get_chip(map, chip, base, FL_CFI_QUERY); | ||
1416 | if (ret) { | ||
1417 | mutex_unlock(&chip->mutex); | ||
1418 | return ret; | ||
1419 | } | ||
1420 | cfi_qry_mode_on(base, map, cfi); | ||
1421 | otp = cfi_read_query(map, base + 0x3 * ofs_factor); | ||
1422 | cfi_qry_mode_off(base, map, cfi); | ||
1423 | put_chip(map, chip, base); | ||
1424 | mutex_unlock(&chip->mutex); | ||
1425 | |||
1426 | if (otp & 0x80) { | ||
1427 | /* factory locked */ | ||
1428 | factory_offset = 0; | ||
1429 | factory_size = 0x100; | ||
1430 | } else { | ||
1431 | /* customer lockable */ | ||
1432 | user_offset = 0; | ||
1433 | user_size = 0x100; | ||
1434 | |||
1435 | mutex_lock(&chip->mutex); | ||
1436 | ret = get_chip(map, chip, base, FL_LOCKING); | ||
1437 | |||
1438 | /* Enter lock register command */ | ||
1439 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, | ||
1440 | chip->start, map, cfi, | ||
1441 | cfi->device_type, NULL); | ||
1442 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, | ||
1443 | chip->start, map, cfi, | ||
1444 | cfi->device_type, NULL); | ||
1445 | cfi_send_gen_cmd(0x40, cfi->addr_unlock1, | ||
1446 | chip->start, map, cfi, | ||
1447 | cfi->device_type, NULL); | ||
1448 | /* read lock register */ | ||
1449 | lockreg = cfi_read_query(map, 0); | ||
1450 | /* exit protection commands */ | ||
1451 | map_write(map, CMD(0x90), chip->start); | ||
1452 | map_write(map, CMD(0x00), chip->start); | ||
1453 | put_chip(map, chip, chip->start); | ||
1454 | mutex_unlock(&chip->mutex); | ||
1455 | |||
1456 | user_locked = ((lockreg & 0x01) == 0x00); | ||
1457 | } | ||
1458 | } | ||
1459 | |||
1460 | otpsize = user_regs ? user_size : factory_size; | ||
1461 | if (!otpsize) | ||
1462 | continue; | ||
1463 | otpoffset = user_regs ? user_offset : factory_offset; | ||
1464 | otplocked = user_regs ? user_locked : 1; | ||
1465 | |||
1466 | if (!action) { | ||
1467 | /* return otpinfo */ | ||
1468 | struct otp_info *otpinfo; | ||
1469 | len -= sizeof(*otpinfo); | ||
1470 | if (len <= 0) | ||
1471 | return -ENOSPC; | ||
1472 | otpinfo = (struct otp_info *)buf; | ||
1473 | otpinfo->start = from; | ||
1474 | otpinfo->length = otpsize; | ||
1475 | otpinfo->locked = otplocked; | ||
1476 | buf += sizeof(*otpinfo); | ||
1477 | *retlen += sizeof(*otpinfo); | ||
1478 | from += otpsize; | ||
1479 | } else if ((from < otpsize) && (len > 0)) { | ||
1480 | size_t size; | ||
1481 | size = (len < otpsize - from) ? len : otpsize - from; | ||
1482 | ret = action(map, chip, otpoffset + from, size, buf, | ||
1483 | otpsize); | ||
1484 | if (ret < 0) | ||
1485 | return ret; | ||
1486 | |||
1487 | buf += size; | ||
1488 | len -= size; | ||
1489 | *retlen += size; | ||
1490 | from = 0; | ||
1491 | } else { | ||
1492 | from -= otpsize; | ||
1493 | } | ||
1494 | } | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static int cfi_amdstd_get_fact_prot_info(struct mtd_info *mtd, size_t len, | ||
1499 | size_t *retlen, struct otp_info *buf) | ||
1500 | { | ||
1501 | return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf, | ||
1502 | NULL, 0); | ||
1503 | } | ||
1504 | |||
1505 | static int cfi_amdstd_get_user_prot_info(struct mtd_info *mtd, size_t len, | ||
1506 | size_t *retlen, struct otp_info *buf) | ||
1507 | { | ||
1508 | return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf, | ||
1509 | NULL, 1); | ||
1510 | } | ||
1511 | |||
1512 | static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | ||
1513 | size_t len, size_t *retlen, | ||
1514 | u_char *buf) | ||
1515 | { | ||
1516 | return cfi_amdstd_otp_walk(mtd, from, len, retlen, | ||
1517 | buf, do_read_secsi_onechip, 0); | ||
1518 | } | ||
1519 | |||
1520 | static int cfi_amdstd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, | ||
1521 | size_t len, size_t *retlen, | ||
1522 | u_char *buf) | ||
1523 | { | ||
1524 | return cfi_amdstd_otp_walk(mtd, from, len, retlen, | ||
1525 | buf, do_read_secsi_onechip, 1); | ||
1526 | } | ||
1527 | |||
1528 | static int cfi_amdstd_write_user_prot_reg(struct mtd_info *mtd, loff_t from, | ||
1529 | size_t len, size_t *retlen, | ||
1530 | u_char *buf) | ||
1531 | { | ||
1532 | return cfi_amdstd_otp_walk(mtd, from, len, retlen, buf, | ||
1533 | do_otp_write, 1); | ||
1534 | } | ||
1535 | |||
1536 | static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, | ||
1537 | size_t len) | ||
1538 | { | ||
1539 | size_t retlen; | ||
1540 | return cfi_amdstd_otp_walk(mtd, from, len, &retlen, NULL, | ||
1541 | do_otp_lock, 1); | ||
1542 | } | ||
1543 | |||
1544 | static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | ||
1545 | unsigned long adr, map_word datum, | ||
1546 | int mode) | ||
1224 | { | 1547 | { |
1225 | struct cfi_private *cfi = map->fldrv_priv; | 1548 | struct cfi_private *cfi = map->fldrv_priv; |
1226 | unsigned long timeo = jiffies + HZ; | 1549 | unsigned long timeo = jiffies + HZ; |
@@ -1241,7 +1564,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1241 | adr += chip->start; | 1564 | adr += chip->start; |
1242 | 1565 | ||
1243 | mutex_lock(&chip->mutex); | 1566 | mutex_lock(&chip->mutex); |
1244 | ret = get_chip(map, chip, adr, FL_WRITING); | 1567 | ret = get_chip(map, chip, adr, mode); |
1245 | if (ret) { | 1568 | if (ret) { |
1246 | mutex_unlock(&chip->mutex); | 1569 | mutex_unlock(&chip->mutex); |
1247 | return ret; | 1570 | return ret; |
@@ -1250,6 +1573,9 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1250 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", | 1573 | pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", |
1251 | __func__, adr, datum.x[0] ); | 1574 | __func__, adr, datum.x[0] ); |
1252 | 1575 | ||
1576 | if (mode == FL_OTP_WRITE) | ||
1577 | otp_enter(map, chip, adr, map_bankwidth(map)); | ||
1578 | |||
1253 | /* | 1579 | /* |
1254 | * Check for a NOP for the case when the datum to write is already | 1580 | * Check for a NOP for the case when the datum to write is already |
1255 | * present - it saves time and works around buggy chips that corrupt | 1581 | * present - it saves time and works around buggy chips that corrupt |
@@ -1266,12 +1592,13 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1266 | XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map)); | 1592 | XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map)); |
1267 | ENABLE_VPP(map); | 1593 | ENABLE_VPP(map); |
1268 | xip_disable(map, chip, adr); | 1594 | xip_disable(map, chip, adr); |
1595 | |||
1269 | retry: | 1596 | retry: |
1270 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1597 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1271 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1598 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1272 | cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1599 | cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1273 | map_write(map, datum, adr); | 1600 | map_write(map, datum, adr); |
1274 | chip->state = FL_WRITING; | 1601 | chip->state = mode; |
1275 | 1602 | ||
1276 | INVALIDATE_CACHE_UDELAY(map, chip, | 1603 | INVALIDATE_CACHE_UDELAY(map, chip, |
1277 | adr, map_bankwidth(map), | 1604 | adr, map_bankwidth(map), |
@@ -1280,7 +1607,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1280 | /* See comment above for timeout value. */ | 1607 | /* See comment above for timeout value. */ |
1281 | timeo = jiffies + uWriteTimeout; | 1608 | timeo = jiffies + uWriteTimeout; |
1282 | for (;;) { | 1609 | for (;;) { |
1283 | if (chip->state != FL_WRITING) { | 1610 | if (chip->state != mode) { |
1284 | /* Someone's suspended the write. Sleep */ | 1611 | /* Someone's suspended the write. Sleep */ |
1285 | DECLARE_WAITQUEUE(wait, current); | 1612 | DECLARE_WAITQUEUE(wait, current); |
1286 | 1613 | ||
@@ -1320,6 +1647,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1320 | } | 1647 | } |
1321 | xip_enable(map, chip, adr); | 1648 | xip_enable(map, chip, adr); |
1322 | op_done: | 1649 | op_done: |
1650 | if (mode == FL_OTP_WRITE) | ||
1651 | otp_exit(map, chip, adr, map_bankwidth(map)); | ||
1323 | chip->state = FL_READY; | 1652 | chip->state = FL_READY; |
1324 | DISABLE_VPP(map); | 1653 | DISABLE_VPP(map); |
1325 | put_chip(map, chip, adr); | 1654 | put_chip(map, chip, adr); |
@@ -1375,7 +1704,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1375 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); | 1704 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); |
1376 | 1705 | ||
1377 | ret = do_write_oneword(map, &cfi->chips[chipnum], | 1706 | ret = do_write_oneword(map, &cfi->chips[chipnum], |
1378 | bus_ofs, tmp_buf); | 1707 | bus_ofs, tmp_buf, FL_WRITING); |
1379 | if (ret) | 1708 | if (ret) |
1380 | return ret; | 1709 | return ret; |
1381 | 1710 | ||
@@ -1399,7 +1728,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1399 | datum = map_word_load(map, buf); | 1728 | datum = map_word_load(map, buf); |
1400 | 1729 | ||
1401 | ret = do_write_oneword(map, &cfi->chips[chipnum], | 1730 | ret = do_write_oneword(map, &cfi->chips[chipnum], |
1402 | ofs, datum); | 1731 | ofs, datum, FL_WRITING); |
1403 | if (ret) | 1732 | if (ret) |
1404 | return ret; | 1733 | return ret; |
1405 | 1734 | ||
@@ -1442,7 +1771,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1442 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); | 1771 | tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); |
1443 | 1772 | ||
1444 | ret = do_write_oneword(map, &cfi->chips[chipnum], | 1773 | ret = do_write_oneword(map, &cfi->chips[chipnum], |
1445 | ofs, tmp_buf); | 1774 | ofs, tmp_buf, FL_WRITING); |
1446 | if (ret) | 1775 | if (ret) |
1447 | return ret; | 1776 | return ret; |
1448 | 1777 | ||
@@ -1462,8 +1791,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1462 | { | 1791 | { |
1463 | struct cfi_private *cfi = map->fldrv_priv; | 1792 | struct cfi_private *cfi = map->fldrv_priv; |
1464 | unsigned long timeo = jiffies + HZ; | 1793 | unsigned long timeo = jiffies + HZ; |
1465 | /* see comments in do_write_oneword() regarding uWriteTimeo. */ | 1794 | /* |
1466 | unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; | 1795 | * Timeout is calculated according to CFI data, if available. |
1796 | * See more comments in cfi_cmdset_0002(). | ||
1797 | */ | ||
1798 | unsigned long uWriteTimeout = | ||
1799 | usecs_to_jiffies(chip->buffer_write_time_max); | ||
1467 | int ret = -EIO; | 1800 | int ret = -EIO; |
1468 | unsigned long cmd_adr; | 1801 | unsigned long cmd_adr; |
1469 | int z, words; | 1802 | int z, words; |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 3e829b37af8d..c8503006f17a 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * <mtd-id> := unique name used in mapping driver/device (mtd->name) | 26 | * <mtd-id> := unique name used in mapping driver/device (mtd->name) |
27 | * <size> := standard linux memsize OR "-" to denote all remaining space | 27 | * <size> := standard linux memsize OR "-" to denote all remaining space |
28 | * size is automatically truncated at end of device | 28 | * size is automatically truncated at end of device |
29 | * if specified or trucated size is 0 the part is skipped | 29 | * if specified or truncated size is 0 the part is skipped |
30 | * <offset> := standard linux memsize | 30 | * <offset> := standard linux memsize |
31 | * if omitted the part will immediately follow the previous part | 31 | * if omitted the part will immediately follow the previous part |
32 | * or 0 if the first part | 32 | * or 0 if the first part |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 2cceebfb251e..effd9a4ef7ee 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -181,12 +181,10 @@ static int parse_name(char **pname, const char *token) | |||
181 | if (len > 64) | 181 | if (len > 64) |
182 | return -ENOSPC; | 182 | return -ENOSPC; |
183 | 183 | ||
184 | name = kmalloc(len, GFP_KERNEL); | 184 | name = kstrdup(token, GFP_KERNEL); |
185 | if (!name) | 185 | if (!name) |
186 | return -ENOMEM; | 186 | return -ENOMEM; |
187 | 187 | ||
188 | strcpy(name, token); | ||
189 | |||
190 | *pname = name; | 188 | *pname = name; |
191 | return 0; | 189 | return 0; |
192 | } | 190 | } |
@@ -195,6 +193,7 @@ static int parse_name(char **pname, const char *token) | |||
195 | static inline void kill_final_newline(char *str) | 193 | static inline void kill_final_newline(char *str) |
196 | { | 194 | { |
197 | char *newline = strrchr(str, '\n'); | 195 | char *newline = strrchr(str, '\n'); |
196 | |||
198 | if (newline && !newline[1]) | 197 | if (newline && !newline[1]) |
199 | *newline = 0; | 198 | *newline = 0; |
200 | } | 199 | } |
@@ -233,7 +232,7 @@ static int phram_setup(const char *val) | |||
233 | strcpy(str, val); | 232 | strcpy(str, val); |
234 | kill_final_newline(str); | 233 | kill_final_newline(str); |
235 | 234 | ||
236 | for (i=0; i<3; i++) | 235 | for (i = 0; i < 3; i++) |
237 | token[i] = strsep(&str, ","); | 236 | token[i] = strsep(&str, ","); |
238 | 237 | ||
239 | if (str) | 238 | if (str) |
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 19d637266fcd..dabf08450d0b 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c | |||
@@ -111,7 +111,6 @@ typedef struct partition_t { | |||
111 | struct mtd_blktrans_dev mbd; | 111 | struct mtd_blktrans_dev mbd; |
112 | uint32_t state; | 112 | uint32_t state; |
113 | uint32_t *VirtualBlockMap; | 113 | uint32_t *VirtualBlockMap; |
114 | uint32_t *VirtualPageMap; | ||
115 | uint32_t FreeTotal; | 114 | uint32_t FreeTotal; |
116 | struct eun_info_t { | 115 | struct eun_info_t { |
117 | uint32_t Offset; | 116 | uint32_t Offset; |
@@ -1035,8 +1034,6 @@ static void ftl_freepart(partition_t *part) | |||
1035 | { | 1034 | { |
1036 | vfree(part->VirtualBlockMap); | 1035 | vfree(part->VirtualBlockMap); |
1037 | part->VirtualBlockMap = NULL; | 1036 | part->VirtualBlockMap = NULL; |
1038 | kfree(part->VirtualPageMap); | ||
1039 | part->VirtualPageMap = NULL; | ||
1040 | kfree(part->EUNInfo); | 1037 | kfree(part->EUNInfo); |
1041 | part->EUNInfo = NULL; | 1038 | part->EUNInfo = NULL; |
1042 | kfree(part->XferInfo); | 1039 | kfree(part->XferInfo); |
@@ -1075,7 +1072,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
1075 | return; | 1072 | return; |
1076 | } | 1073 | } |
1077 | 1074 | ||
1078 | ftl_freepart(partition); | ||
1079 | kfree(partition); | 1075 | kfree(partition); |
1080 | } | 1076 | } |
1081 | 1077 | ||
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c index 146b6047ed2b..a84fdfb10518 100644 --- a/drivers/mtd/maps/rbtx4939-flash.c +++ b/drivers/mtd/maps/rbtx4939-flash.c | |||
@@ -35,8 +35,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev) | |||
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | if (info->mtd) { | 37 | if (info->mtd) { |
38 | struct rbtx4939_flash_data *pdata = dev_get_platdata(&dev->dev); | ||
39 | |||
40 | mtd_device_unregister(info->mtd); | 38 | mtd_device_unregister(info->mtd); |
41 | map_destroy(info->mtd); | 39 | map_destroy(info->mtd); |
42 | } | 40 | } |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index d201feeb3ca6..e4831b4159db 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -298,6 +298,47 @@ static ssize_t mtd_ecc_step_size_show(struct device *dev, | |||
298 | } | 298 | } |
299 | static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL); | 299 | static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL); |
300 | 300 | ||
301 | static ssize_t mtd_ecc_stats_corrected_show(struct device *dev, | ||
302 | struct device_attribute *attr, char *buf) | ||
303 | { | ||
304 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
305 | struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; | ||
306 | |||
307 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->corrected); | ||
308 | } | ||
309 | static DEVICE_ATTR(corrected_bits, S_IRUGO, | ||
310 | mtd_ecc_stats_corrected_show, NULL); | ||
311 | |||
312 | static ssize_t mtd_ecc_stats_errors_show(struct device *dev, | ||
313 | struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
316 | struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; | ||
317 | |||
318 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->failed); | ||
319 | } | ||
320 | static DEVICE_ATTR(ecc_failures, S_IRUGO, mtd_ecc_stats_errors_show, NULL); | ||
321 | |||
322 | static ssize_t mtd_badblocks_show(struct device *dev, | ||
323 | struct device_attribute *attr, char *buf) | ||
324 | { | ||
325 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
326 | struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; | ||
327 | |||
328 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->badblocks); | ||
329 | } | ||
330 | static DEVICE_ATTR(bad_blocks, S_IRUGO, mtd_badblocks_show, NULL); | ||
331 | |||
332 | static ssize_t mtd_bbtblocks_show(struct device *dev, | ||
333 | struct device_attribute *attr, char *buf) | ||
334 | { | ||
335 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
336 | struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; | ||
337 | |||
338 | return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->bbtblocks); | ||
339 | } | ||
340 | static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL); | ||
341 | |||
301 | static struct attribute *mtd_attrs[] = { | 342 | static struct attribute *mtd_attrs[] = { |
302 | &dev_attr_type.attr, | 343 | &dev_attr_type.attr, |
303 | &dev_attr_flags.attr, | 344 | &dev_attr_flags.attr, |
@@ -310,6 +351,10 @@ static struct attribute *mtd_attrs[] = { | |||
310 | &dev_attr_name.attr, | 351 | &dev_attr_name.attr, |
311 | &dev_attr_ecc_strength.attr, | 352 | &dev_attr_ecc_strength.attr, |
312 | &dev_attr_ecc_step_size.attr, | 353 | &dev_attr_ecc_step_size.attr, |
354 | &dev_attr_corrected_bits.attr, | ||
355 | &dev_attr_ecc_failures.attr, | ||
356 | &dev_attr_bad_blocks.attr, | ||
357 | &dev_attr_bbt_blocks.attr, | ||
313 | &dev_attr_bitflip_threshold.attr, | 358 | &dev_attr_bitflip_threshold.attr, |
314 | NULL, | 359 | NULL, |
315 | }; | 360 | }; |
@@ -998,12 +1043,22 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
998 | } | 1043 | } |
999 | EXPORT_SYMBOL_GPL(mtd_is_locked); | 1044 | EXPORT_SYMBOL_GPL(mtd_is_locked); |
1000 | 1045 | ||
1001 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) | 1046 | int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs) |
1002 | { | 1047 | { |
1003 | if (!mtd->_block_isbad) | 1048 | if (ofs < 0 || ofs > mtd->size) |
1049 | return -EINVAL; | ||
1050 | if (!mtd->_block_isreserved) | ||
1004 | return 0; | 1051 | return 0; |
1052 | return mtd->_block_isreserved(mtd, ofs); | ||
1053 | } | ||
1054 | EXPORT_SYMBOL_GPL(mtd_block_isreserved); | ||
1055 | |||
1056 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) | ||
1057 | { | ||
1005 | if (ofs < 0 || ofs > mtd->size) | 1058 | if (ofs < 0 || ofs > mtd->size) |
1006 | return -EINVAL; | 1059 | return -EINVAL; |
1060 | if (!mtd->_block_isbad) | ||
1061 | return 0; | ||
1007 | return mtd->_block_isbad(mtd, ofs); | 1062 | return mtd->_block_isbad(mtd, ofs); |
1008 | } | 1063 | } |
1009 | EXPORT_SYMBOL_GPL(mtd_block_isbad); | 1064 | EXPORT_SYMBOL_GPL(mtd_block_isbad); |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 1ca9aec141ff..a3e3a7d074d5 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -290,6 +290,13 @@ static void part_resume(struct mtd_info *mtd) | |||
290 | part->master->_resume(part->master); | 290 | part->master->_resume(part->master); |
291 | } | 291 | } |
292 | 292 | ||
293 | static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs) | ||
294 | { | ||
295 | struct mtd_part *part = PART(mtd); | ||
296 | ofs += part->offset; | ||
297 | return part->master->_block_isreserved(part->master, ofs); | ||
298 | } | ||
299 | |||
293 | static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) | 300 | static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) |
294 | { | 301 | { |
295 | struct mtd_part *part = PART(mtd); | 302 | struct mtd_part *part = PART(mtd); |
@@ -422,6 +429,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
422 | slave->mtd._unlock = part_unlock; | 429 | slave->mtd._unlock = part_unlock; |
423 | if (master->_is_locked) | 430 | if (master->_is_locked) |
424 | slave->mtd._is_locked = part_is_locked; | 431 | slave->mtd._is_locked = part_is_locked; |
432 | if (master->_block_isreserved) | ||
433 | slave->mtd._block_isreserved = part_block_isreserved; | ||
425 | if (master->_block_isbad) | 434 | if (master->_block_isbad) |
426 | slave->mtd._block_isbad = part_block_isbad; | 435 | slave->mtd._block_isbad = part_block_isbad; |
427 | if (master->_block_markbad) | 436 | if (master->_block_markbad) |
@@ -526,7 +535,9 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
526 | uint64_t offs = 0; | 535 | uint64_t offs = 0; |
527 | 536 | ||
528 | while (offs < slave->mtd.size) { | 537 | while (offs < slave->mtd.size) { |
529 | if (mtd_block_isbad(master, offs + slave->offset)) | 538 | if (mtd_block_isreserved(master, offs + slave->offset)) |
539 | slave->mtd.ecc_stats.bbtblocks++; | ||
540 | else if (mtd_block_isbad(master, offs + slave->offset)) | ||
530 | slave->mtd.ecc_stats.badblocks++; | 541 | slave->mtd.ecc_stats.badblocks++; |
531 | offs += slave->mtd.erasesize; | 542 | offs += slave->mtd.erasesize; |
532 | } | 543 | } |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 542b5689eb63..a035e7cc6d46 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -50,4 +50,4 @@ obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | |||
50 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | 50 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
51 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | 51 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ |
52 | 52 | ||
53 | nand-objs := nand_base.o nand_bbt.o | 53 | nand-objs := nand_base.o nand_bbt.o nand_timings.o |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4ce181a35bcd..e321c564ff05 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -97,7 +97,9 @@ struct atmel_nfc { | |||
97 | bool write_by_sram; | 97 | bool write_by_sram; |
98 | 98 | ||
99 | bool is_initialized; | 99 | bool is_initialized; |
100 | struct completion comp_nfc; | 100 | struct completion comp_ready; |
101 | struct completion comp_cmd_done; | ||
102 | struct completion comp_xfer_done; | ||
101 | 103 | ||
102 | /* Point to the sram bank which include readed data via NFC */ | 104 | /* Point to the sram bank which include readed data via NFC */ |
103 | void __iomem *data_in_sram; | 105 | void __iomem *data_in_sram; |
@@ -861,12 +863,11 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
861 | { | 863 | { |
862 | struct nand_chip *nand_chip = mtd->priv; | 864 | struct nand_chip *nand_chip = mtd->priv; |
863 | struct atmel_nand_host *host = nand_chip->priv; | 865 | struct atmel_nand_host *host = nand_chip->priv; |
864 | int i, err_nbr, eccbytes; | 866 | int i, err_nbr; |
865 | uint8_t *buf_pos; | 867 | uint8_t *buf_pos; |
866 | int total_err = 0; | 868 | int total_err = 0; |
867 | 869 | ||
868 | eccbytes = nand_chip->ecc.bytes; | 870 | for (i = 0; i < nand_chip->ecc.total; i++) |
869 | for (i = 0; i < eccbytes; i++) | ||
870 | if (ecc[i] != 0xff) | 871 | if (ecc[i] != 0xff) |
871 | goto normal_check; | 872 | goto normal_check; |
872 | /* Erased page, return OK */ | 873 | /* Erased page, return OK */ |
@@ -928,7 +929,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
928 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | 929 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) |
929 | { | 930 | { |
930 | struct atmel_nand_host *host = chip->priv; | 931 | struct atmel_nand_host *host = chip->priv; |
931 | int eccsize = chip->ecc.size; | 932 | int eccsize = chip->ecc.size * chip->ecc.steps; |
932 | uint8_t *oob = chip->oob_poi; | 933 | uint8_t *oob = chip->oob_poi; |
933 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 934 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
934 | uint32_t stat; | 935 | uint32_t stat; |
@@ -1169,8 +1170,7 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1169 | goto err; | 1170 | goto err; |
1170 | } | 1171 | } |
1171 | 1172 | ||
1172 | /* ECC is calculated for the whole page (1 step) */ | 1173 | nand_chip->ecc.size = sector_size; |
1173 | nand_chip->ecc.size = mtd->writesize; | ||
1174 | 1174 | ||
1175 | /* set ECC page size and oob layout */ | 1175 | /* set ECC page size and oob layout */ |
1176 | switch (mtd->writesize) { | 1176 | switch (mtd->writesize) { |
@@ -1185,18 +1185,20 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1185 | host->pmecc_index_of = host->pmecc_rom_base + | 1185 | host->pmecc_index_of = host->pmecc_rom_base + |
1186 | host->pmecc_lookup_table_offset; | 1186 | host->pmecc_lookup_table_offset; |
1187 | 1187 | ||
1188 | nand_chip->ecc.steps = 1; | 1188 | nand_chip->ecc.steps = host->pmecc_sector_number; |
1189 | nand_chip->ecc.strength = cap; | 1189 | nand_chip->ecc.strength = cap; |
1190 | nand_chip->ecc.bytes = host->pmecc_bytes_per_sector * | 1190 | nand_chip->ecc.bytes = host->pmecc_bytes_per_sector; |
1191 | nand_chip->ecc.total = host->pmecc_bytes_per_sector * | ||
1191 | host->pmecc_sector_number; | 1192 | host->pmecc_sector_number; |
1192 | if (nand_chip->ecc.bytes > mtd->oobsize - 2) { | 1193 | if (nand_chip->ecc.total > mtd->oobsize - 2) { |
1193 | dev_err(host->dev, "No room for ECC bytes\n"); | 1194 | dev_err(host->dev, "No room for ECC bytes\n"); |
1194 | err_no = -EINVAL; | 1195 | err_no = -EINVAL; |
1195 | goto err; | 1196 | goto err; |
1196 | } | 1197 | } |
1197 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, | 1198 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, |
1198 | mtd->oobsize, | 1199 | mtd->oobsize, |
1199 | nand_chip->ecc.bytes); | 1200 | nand_chip->ecc.total); |
1201 | |||
1200 | nand_chip->ecc.layout = &atmel_pmecc_oobinfo; | 1202 | nand_chip->ecc.layout = &atmel_pmecc_oobinfo; |
1201 | break; | 1203 | break; |
1202 | case 512: | 1204 | case 512: |
@@ -1572,49 +1574,104 @@ static int atmel_hw_nand_init_params(struct platform_device *pdev, | |||
1572 | return 0; | 1574 | return 0; |
1573 | } | 1575 | } |
1574 | 1576 | ||
1577 | static inline u32 nfc_read_status(struct atmel_nand_host *host) | ||
1578 | { | ||
1579 | u32 err_flags = NFC_SR_DTOE | NFC_SR_UNDEF | NFC_SR_AWB | NFC_SR_ASE; | ||
1580 | u32 nfc_status = nfc_readl(host->nfc->hsmc_regs, SR); | ||
1581 | |||
1582 | if (unlikely(nfc_status & err_flags)) { | ||
1583 | if (nfc_status & NFC_SR_DTOE) | ||
1584 | dev_err(host->dev, "NFC: Waiting Nand R/B Timeout Error\n"); | ||
1585 | else if (nfc_status & NFC_SR_UNDEF) | ||
1586 | dev_err(host->dev, "NFC: Access Undefined Area Error\n"); | ||
1587 | else if (nfc_status & NFC_SR_AWB) | ||
1588 | dev_err(host->dev, "NFC: Access memory While NFC is busy\n"); | ||
1589 | else if (nfc_status & NFC_SR_ASE) | ||
1590 | dev_err(host->dev, "NFC: Access memory Size Error\n"); | ||
1591 | } | ||
1592 | |||
1593 | return nfc_status; | ||
1594 | } | ||
1595 | |||
1575 | /* SMC interrupt service routine */ | 1596 | /* SMC interrupt service routine */ |
1576 | static irqreturn_t hsmc_interrupt(int irq, void *dev_id) | 1597 | static irqreturn_t hsmc_interrupt(int irq, void *dev_id) |
1577 | { | 1598 | { |
1578 | struct atmel_nand_host *host = dev_id; | 1599 | struct atmel_nand_host *host = dev_id; |
1579 | u32 status, mask, pending; | 1600 | u32 status, mask, pending; |
1580 | irqreturn_t ret = IRQ_HANDLED; | 1601 | irqreturn_t ret = IRQ_NONE; |
1581 | 1602 | ||
1582 | status = nfc_readl(host->nfc->hsmc_regs, SR); | 1603 | status = nfc_read_status(host); |
1583 | mask = nfc_readl(host->nfc->hsmc_regs, IMR); | 1604 | mask = nfc_readl(host->nfc->hsmc_regs, IMR); |
1584 | pending = status & mask; | 1605 | pending = status & mask; |
1585 | 1606 | ||
1586 | if (pending & NFC_SR_XFR_DONE) { | 1607 | if (pending & NFC_SR_XFR_DONE) { |
1587 | complete(&host->nfc->comp_nfc); | 1608 | complete(&host->nfc->comp_xfer_done); |
1588 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE); | 1609 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE); |
1589 | } else if (pending & NFC_SR_RB_EDGE) { | 1610 | ret = IRQ_HANDLED; |
1590 | complete(&host->nfc->comp_nfc); | 1611 | } |
1612 | if (pending & NFC_SR_RB_EDGE) { | ||
1613 | complete(&host->nfc->comp_ready); | ||
1591 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE); | 1614 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE); |
1592 | } else if (pending & NFC_SR_CMD_DONE) { | 1615 | ret = IRQ_HANDLED; |
1593 | complete(&host->nfc->comp_nfc); | 1616 | } |
1617 | if (pending & NFC_SR_CMD_DONE) { | ||
1618 | complete(&host->nfc->comp_cmd_done); | ||
1594 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE); | 1619 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE); |
1595 | } else { | 1620 | ret = IRQ_HANDLED; |
1596 | ret = IRQ_NONE; | ||
1597 | } | 1621 | } |
1598 | 1622 | ||
1599 | return ret; | 1623 | return ret; |
1600 | } | 1624 | } |
1601 | 1625 | ||
1602 | /* NFC(Nand Flash Controller) related functions */ | 1626 | /* NFC(Nand Flash Controller) related functions */ |
1603 | static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) | 1627 | static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag) |
1604 | { | 1628 | { |
1605 | unsigned long timeout; | 1629 | if (flag & NFC_SR_XFR_DONE) |
1606 | init_completion(&host->nfc->comp_nfc); | 1630 | init_completion(&host->nfc->comp_xfer_done); |
1631 | |||
1632 | if (flag & NFC_SR_RB_EDGE) | ||
1633 | init_completion(&host->nfc->comp_ready); | ||
1634 | |||
1635 | if (flag & NFC_SR_CMD_DONE) | ||
1636 | init_completion(&host->nfc->comp_cmd_done); | ||
1607 | 1637 | ||
1608 | /* Enable interrupt that need to wait for */ | 1638 | /* Enable interrupt that need to wait for */ |
1609 | nfc_writel(host->nfc->hsmc_regs, IER, flag); | 1639 | nfc_writel(host->nfc->hsmc_regs, IER, flag); |
1640 | } | ||
1610 | 1641 | ||
1611 | timeout = wait_for_completion_timeout(&host->nfc->comp_nfc, | 1642 | static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) |
1612 | msecs_to_jiffies(NFC_TIME_OUT_MS)); | 1643 | { |
1613 | if (timeout) | 1644 | int i, index = 0; |
1614 | return 0; | 1645 | struct completion *comp[3]; /* Support 3 interrupt completion */ |
1615 | 1646 | ||
1616 | /* Time out to wait for the interrupt */ | 1647 | if (flag & NFC_SR_XFR_DONE) |
1648 | comp[index++] = &host->nfc->comp_xfer_done; | ||
1649 | |||
1650 | if (flag & NFC_SR_RB_EDGE) | ||
1651 | comp[index++] = &host->nfc->comp_ready; | ||
1652 | |||
1653 | if (flag & NFC_SR_CMD_DONE) | ||
1654 | comp[index++] = &host->nfc->comp_cmd_done; | ||
1655 | |||
1656 | if (index == 0) { | ||
1657 | dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag); | ||
1658 | return -EINVAL; | ||
1659 | } | ||
1660 | |||
1661 | for (i = 0; i < index; i++) { | ||
1662 | if (wait_for_completion_timeout(comp[i], | ||
1663 | msecs_to_jiffies(NFC_TIME_OUT_MS))) | ||
1664 | continue; /* wait for next completion */ | ||
1665 | else | ||
1666 | goto err_timeout; | ||
1667 | } | ||
1668 | |||
1669 | return 0; | ||
1670 | |||
1671 | err_timeout: | ||
1617 | dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag); | 1672 | dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag); |
1673 | /* Disable the interrupt as it is not handled by interrupt handler */ | ||
1674 | nfc_writel(host->nfc->hsmc_regs, IDR, flag); | ||
1618 | return -ETIMEDOUT; | 1675 | return -ETIMEDOUT; |
1619 | } | 1676 | } |
1620 | 1677 | ||
@@ -1622,6 +1679,9 @@ static int nfc_send_command(struct atmel_nand_host *host, | |||
1622 | unsigned int cmd, unsigned int addr, unsigned char cycle0) | 1679 | unsigned int cmd, unsigned int addr, unsigned char cycle0) |
1623 | { | 1680 | { |
1624 | unsigned long timeout; | 1681 | unsigned long timeout; |
1682 | u32 flag = NFC_SR_CMD_DONE; | ||
1683 | flag |= cmd & NFCADDR_CMD_DATAEN ? NFC_SR_XFR_DONE : 0; | ||
1684 | |||
1625 | dev_dbg(host->dev, | 1685 | dev_dbg(host->dev, |
1626 | "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n", | 1686 | "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n", |
1627 | cmd, addr, cycle0); | 1687 | cmd, addr, cycle0); |
@@ -1635,18 +1695,28 @@ static int nfc_send_command(struct atmel_nand_host *host, | |||
1635 | return -ETIMEDOUT; | 1695 | return -ETIMEDOUT; |
1636 | } | 1696 | } |
1637 | } | 1697 | } |
1698 | |||
1699 | nfc_prepare_interrupt(host, flag); | ||
1638 | nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0); | 1700 | nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0); |
1639 | nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs); | 1701 | nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs); |
1640 | return nfc_wait_interrupt(host, NFC_SR_CMD_DONE); | 1702 | return nfc_wait_interrupt(host, flag); |
1641 | } | 1703 | } |
1642 | 1704 | ||
1643 | static int nfc_device_ready(struct mtd_info *mtd) | 1705 | static int nfc_device_ready(struct mtd_info *mtd) |
1644 | { | 1706 | { |
1707 | u32 status, mask; | ||
1645 | struct nand_chip *nand_chip = mtd->priv; | 1708 | struct nand_chip *nand_chip = mtd->priv; |
1646 | struct atmel_nand_host *host = nand_chip->priv; | 1709 | struct atmel_nand_host *host = nand_chip->priv; |
1647 | if (!nfc_wait_interrupt(host, NFC_SR_RB_EDGE)) | 1710 | |
1648 | return 1; | 1711 | status = nfc_read_status(host); |
1649 | return 0; | 1712 | mask = nfc_readl(host->nfc->hsmc_regs, IMR); |
1713 | |||
1714 | /* The mask should be 0. If not we may lost interrupts */ | ||
1715 | if (unlikely(mask & status)) | ||
1716 | dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n", | ||
1717 | mask & status); | ||
1718 | |||
1719 | return status & NFC_SR_RB_EDGE; | ||
1650 | } | 1720 | } |
1651 | 1721 | ||
1652 | static void nfc_select_chip(struct mtd_info *mtd, int chip) | 1722 | static void nfc_select_chip(struct mtd_info *mtd, int chip) |
@@ -1795,10 +1865,6 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, | |||
1795 | nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; | 1865 | nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; |
1796 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); | 1866 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); |
1797 | 1867 | ||
1798 | if (dataen == NFCADDR_CMD_DATAEN) | ||
1799 | if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE)) | ||
1800 | dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n"); | ||
1801 | |||
1802 | /* | 1868 | /* |
1803 | * Program and erase have their own busy handlers status, sequential | 1869 | * Program and erase have their own busy handlers status, sequential |
1804 | * in, and deplete1 need no delay. | 1870 | * in, and deplete1 need no delay. |
@@ -1823,6 +1889,7 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, | |||
1823 | } | 1889 | } |
1824 | /* fall through */ | 1890 | /* fall through */ |
1825 | default: | 1891 | default: |
1892 | nfc_prepare_interrupt(host, NFC_SR_RB_EDGE); | ||
1826 | nfc_wait_interrupt(host, NFC_SR_RB_EDGE); | 1893 | nfc_wait_interrupt(host, NFC_SR_RB_EDGE); |
1827 | } | 1894 | } |
1828 | } | 1895 | } |
@@ -2209,6 +2276,9 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev) | |||
2209 | } | 2276 | } |
2210 | } | 2277 | } |
2211 | 2278 | ||
2279 | nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff); | ||
2280 | nfc_readl(nfc->hsmc_regs, SR); /* clear the NFC_SR */ | ||
2281 | |||
2212 | nfc->is_initialized = true; | 2282 | nfc->is_initialized = true; |
2213 | dev_info(&pdev->dev, "NFC is probed.\n"); | 2283 | dev_info(&pdev->dev, "NFC is probed.\n"); |
2214 | return 0; | 2284 | return 0; |
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h index 4efd117cd3a3..85b8ca6af7d2 100644 --- a/drivers/mtd/nand/atmel_nand_nfc.h +++ b/drivers/mtd/nand/atmel_nand_nfc.h | |||
@@ -37,6 +37,10 @@ | |||
37 | #define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */ | 37 | #define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */ |
38 | #define NFC_SR_XFR_DONE (1 << 16) | 38 | #define NFC_SR_XFR_DONE (1 << 16) |
39 | #define NFC_SR_CMD_DONE (1 << 17) | 39 | #define NFC_SR_CMD_DONE (1 << 17) |
40 | #define NFC_SR_DTOE (1 << 20) | ||
41 | #define NFC_SR_UNDEF (1 << 21) | ||
42 | #define NFC_SR_AWB (1 << 22) | ||
43 | #define NFC_SR_ASE (1 << 23) | ||
40 | #define NFC_SR_RB_EDGE (1 << 24) | 44 | #define NFC_SR_RB_EDGE (1 << 24) |
41 | 45 | ||
42 | #define ATMEL_HSMC_NFC_IER 0x0c | 46 | #define ATMEL_HSMC_NFC_IER 0x0c |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 722898aea7a6..871c4f712654 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -830,34 +830,10 @@ out_err: | |||
830 | return err; | 830 | return err; |
831 | } | 831 | } |
832 | 832 | ||
833 | /* PM Support */ | ||
834 | #ifdef CONFIG_PM | ||
835 | |||
836 | static int bf5xx_nand_suspend(struct platform_device *dev, pm_message_t pm) | ||
837 | { | ||
838 | struct bf5xx_nand_info *info = platform_get_drvdata(dev); | ||
839 | |||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static int bf5xx_nand_resume(struct platform_device *dev) | ||
844 | { | ||
845 | struct bf5xx_nand_info *info = platform_get_drvdata(dev); | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | #else | ||
851 | #define bf5xx_nand_suspend NULL | ||
852 | #define bf5xx_nand_resume NULL | ||
853 | #endif | ||
854 | |||
855 | /* driver device registration */ | 833 | /* driver device registration */ |
856 | static struct platform_driver bf5xx_nand_driver = { | 834 | static struct platform_driver bf5xx_nand_driver = { |
857 | .probe = bf5xx_nand_probe, | 835 | .probe = bf5xx_nand_probe, |
858 | .remove = bf5xx_nand_remove, | 836 | .remove = bf5xx_nand_remove, |
859 | .suspend = bf5xx_nand_suspend, | ||
860 | .resume = bf5xx_nand_resume, | ||
861 | .driver = { | 837 | .driver = { |
862 | .name = DRV_NAME, | 838 | .name = DRV_NAME, |
863 | .owner = THIS_MODULE, | 839 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 9f2012a3e764..0b071a3136a2 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -473,7 +473,7 @@ static void detect_partition_feature(struct denali_nand_info *denali) | |||
473 | static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | 473 | static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) |
474 | { | 474 | { |
475 | uint16_t status = PASS; | 475 | uint16_t status = PASS; |
476 | uint32_t id_bytes[5], addr; | 476 | uint32_t id_bytes[8], addr; |
477 | uint8_t i, maf_id, device_id; | 477 | uint8_t i, maf_id, device_id; |
478 | 478 | ||
479 | dev_dbg(denali->dev, | 479 | dev_dbg(denali->dev, |
@@ -488,7 +488,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
488 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); | 488 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
489 | index_addr(denali, (uint32_t)addr | 0, 0x90); | 489 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
490 | index_addr(denali, (uint32_t)addr | 1, 0); | 490 | index_addr(denali, (uint32_t)addr | 1, 0); |
491 | for (i = 0; i < 5; i++) | 491 | for (i = 0; i < 8; i++) |
492 | index_addr_read_data(denali, addr | 2, &id_bytes[i]); | 492 | index_addr_read_data(denali, addr | 2, &id_bytes[i]); |
493 | maf_id = id_bytes[0]; | 493 | maf_id = id_bytes[0]; |
494 | device_id = id_bytes[1]; | 494 | device_id = id_bytes[1]; |
@@ -1276,7 +1276,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1276 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); | 1276 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
1277 | index_addr(denali, (uint32_t)addr | 0, 0x90); | 1277 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
1278 | index_addr(denali, (uint32_t)addr | 1, 0); | 1278 | index_addr(denali, (uint32_t)addr | 1, 0); |
1279 | for (i = 0; i < 5; i++) { | 1279 | for (i = 0; i < 8; i++) { |
1280 | index_addr_read_data(denali, | 1280 | index_addr_read_data(denali, |
1281 | (uint32_t)addr | 2, | 1281 | (uint32_t)addr | 2, |
1282 | &id); | 1282 | &id); |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index f638cd8077ca..959cb9b70310 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -285,9 +285,8 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) | |||
285 | geo->ecc_strength = get_ecc_strength(this); | 285 | geo->ecc_strength = get_ecc_strength(this); |
286 | if (!gpmi_check_ecc(this)) { | 286 | if (!gpmi_check_ecc(this)) { |
287 | dev_err(this->dev, | 287 | dev_err(this->dev, |
288 | "We can not support this nand chip." | 288 | "required ecc strength of the NAND chip: %d is not supported by the GPMI controller (%d)\n", |
289 | " Its required ecc strength(%d) is beyond our" | 289 | geo->ecc_strength, |
290 | " capability(%d).\n", geo->ecc_strength, | ||
291 | this->devdata->bch_max_ecc_strength); | 290 | this->devdata->bch_max_ecc_strength); |
292 | return -EINVAL; | 291 | return -EINVAL; |
293 | } | 292 | } |
@@ -1082,6 +1081,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1082 | int first, last, marker_pos; | 1081 | int first, last, marker_pos; |
1083 | int ecc_parity_size; | 1082 | int ecc_parity_size; |
1084 | int col = 0; | 1083 | int col = 0; |
1084 | int old_swap_block_mark = this->swap_block_mark; | ||
1085 | 1085 | ||
1086 | /* The size of ECC parity */ | 1086 | /* The size of ECC parity */ |
1087 | ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; | 1087 | ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; |
@@ -1090,17 +1090,21 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1090 | first = offs / size; | 1090 | first = offs / size; |
1091 | last = (offs + len - 1) / size; | 1091 | last = (offs + len - 1) / size; |
1092 | 1092 | ||
1093 | /* | 1093 | if (this->swap_block_mark) { |
1094 | * Find the chunk which contains the Block Marker. If this chunk is | 1094 | /* |
1095 | * in the range of [first, last], we have to read out the whole page. | 1095 | * Find the chunk which contains the Block Marker. |
1096 | * Why? since we had swapped the data at the position of Block Marker | 1096 | * If this chunk is in the range of [first, last], |
1097 | * to the metadata which is bound with the chunk 0. | 1097 | * we have to read out the whole page. |
1098 | */ | 1098 | * Why? since we had swapped the data at the position of Block |
1099 | marker_pos = geo->block_mark_byte_offset / size; | 1099 | * Marker to the metadata which is bound with the chunk 0. |
1100 | if (last >= marker_pos && first <= marker_pos) { | 1100 | */ |
1101 | dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n", | 1101 | marker_pos = geo->block_mark_byte_offset / size; |
1102 | if (last >= marker_pos && first <= marker_pos) { | ||
1103 | dev_dbg(this->dev, | ||
1104 | "page:%d, first:%d, last:%d, marker at:%d\n", | ||
1102 | page, first, last, marker_pos); | 1105 | page, first, last, marker_pos); |
1103 | return gpmi_ecc_read_page(mtd, chip, buf, 0, page); | 1106 | return gpmi_ecc_read_page(mtd, chip, buf, 0, page); |
1107 | } | ||
1104 | } | 1108 | } |
1105 | 1109 | ||
1106 | meta = geo->metadata_size; | 1110 | meta = geo->metadata_size; |
@@ -1146,7 +1150,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1146 | writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); | 1150 | writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); |
1147 | writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); | 1151 | writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); |
1148 | this->bch_geometry = old_geo; | 1152 | this->bch_geometry = old_geo; |
1149 | this->swap_block_mark = true; | 1153 | this->swap_block_mark = old_swap_block_mark; |
1150 | 1154 | ||
1151 | return max_bitflips; | 1155 | return max_bitflips; |
1152 | } | 1156 | } |
@@ -1180,7 +1184,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1180 | 1184 | ||
1181 | /* Handle block mark swapping. */ | 1185 | /* Handle block mark swapping. */ |
1182 | block_mark_swapping(this, | 1186 | block_mark_swapping(this, |
1183 | (void *) payload_virt, (void *) auxiliary_virt); | 1187 | (void *)payload_virt, (void *)auxiliary_virt); |
1184 | } else { | 1188 | } else { |
1185 | /* | 1189 | /* |
1186 | * If control arrives here, we're not doing block mark swapping, | 1190 | * If control arrives here, we're not doing block mark swapping, |
@@ -1310,10 +1314,10 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
1310 | 1314 | ||
1311 | /* | 1315 | /* |
1312 | * Now, we want to make sure the block mark is correct. In the | 1316 | * Now, we want to make sure the block mark is correct. In the |
1313 | * Swapping/Raw case, we already have it. Otherwise, we need to | 1317 | * non-transcribing case (!GPMI_IS_MX23()), we already have it. |
1314 | * explicitly read it. | 1318 | * Otherwise, we need to explicitly read it. |
1315 | */ | 1319 | */ |
1316 | if (!this->swap_block_mark) { | 1320 | if (GPMI_IS_MX23(this)) { |
1317 | /* Read the block mark into the first byte of the OOB buffer. */ | 1321 | /* Read the block mark into the first byte of the OOB buffer. */ |
1318 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | 1322 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |
1319 | chip->oob_poi[0] = chip->read_byte(mtd); | 1323 | chip->oob_poi[0] = chip->read_byte(mtd); |
@@ -1354,7 +1358,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1354 | chipnr = (int)(ofs >> chip->chip_shift); | 1358 | chipnr = (int)(ofs >> chip->chip_shift); |
1355 | chip->select_chip(mtd, chipnr); | 1359 | chip->select_chip(mtd, chipnr); |
1356 | 1360 | ||
1357 | column = this->swap_block_mark ? mtd->writesize : 0; | 1361 | column = !GPMI_IS_MX23(this) ? mtd->writesize : 0; |
1358 | 1362 | ||
1359 | /* Write the block mark. */ | 1363 | /* Write the block mark. */ |
1360 | block_mark = this->data_buffer_dma; | 1364 | block_mark = this->data_buffer_dma; |
@@ -1597,8 +1601,9 @@ static int mx23_boot_init(struct gpmi_nand_data *this) | |||
1597 | dev_dbg(dev, "Transcribing mark in block %u\n", block); | 1601 | dev_dbg(dev, "Transcribing mark in block %u\n", block); |
1598 | ret = chip->block_markbad(mtd, byte); | 1602 | ret = chip->block_markbad(mtd, byte); |
1599 | if (ret) | 1603 | if (ret) |
1600 | dev_err(dev, "Failed to mark block bad with " | 1604 | dev_err(dev, |
1601 | "ret %d\n", ret); | 1605 | "Failed to mark block bad with ret %d\n", |
1606 | ret); | ||
1602 | } | 1607 | } |
1603 | } | 1608 | } |
1604 | 1609 | ||
@@ -1649,9 +1654,6 @@ static int gpmi_init_last(struct gpmi_nand_data *this) | |||
1649 | struct bch_geometry *bch_geo = &this->bch_geometry; | 1654 | struct bch_geometry *bch_geo = &this->bch_geometry; |
1650 | int ret; | 1655 | int ret; |
1651 | 1656 | ||
1652 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | ||
1653 | this->swap_block_mark = !GPMI_IS_MX23(this); | ||
1654 | |||
1655 | /* Set up the medium geometry */ | 1657 | /* Set up the medium geometry */ |
1656 | ret = gpmi_set_geometry(this); | 1658 | ret = gpmi_set_geometry(this); |
1657 | if (ret) | 1659 | if (ret) |
@@ -1715,9 +1717,20 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) | |||
1715 | chip->badblock_pattern = &gpmi_bbt_descr; | 1717 | chip->badblock_pattern = &gpmi_bbt_descr; |
1716 | chip->block_markbad = gpmi_block_markbad; | 1718 | chip->block_markbad = gpmi_block_markbad; |
1717 | chip->options |= NAND_NO_SUBPAGE_WRITE; | 1719 | chip->options |= NAND_NO_SUBPAGE_WRITE; |
1718 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) | 1720 | |
1721 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | ||
1722 | this->swap_block_mark = !GPMI_IS_MX23(this); | ||
1723 | |||
1724 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) { | ||
1719 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | 1725 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; |
1720 | 1726 | ||
1727 | if (of_property_read_bool(this->dev->of_node, | ||
1728 | "fsl,no-blockmark-swap")) | ||
1729 | this->swap_block_mark = false; | ||
1730 | } | ||
1731 | dev_dbg(this->dev, "Blockmark swapping %sabled\n", | ||
1732 | this->swap_block_mark ? "en" : "dis"); | ||
1733 | |||
1721 | /* | 1734 | /* |
1722 | * Allocate a temporary DMA buffer for reading ID in the | 1735 | * Allocate a temporary DMA buffer for reading ID in the |
1723 | * nand_scan_ident(). | 1736 | * nand_scan_ident(). |
@@ -1760,16 +1773,16 @@ err_out: | |||
1760 | static const struct of_device_id gpmi_nand_id_table[] = { | 1773 | static const struct of_device_id gpmi_nand_id_table[] = { |
1761 | { | 1774 | { |
1762 | .compatible = "fsl,imx23-gpmi-nand", | 1775 | .compatible = "fsl,imx23-gpmi-nand", |
1763 | .data = (void *)&gpmi_devdata_imx23, | 1776 | .data = &gpmi_devdata_imx23, |
1764 | }, { | 1777 | }, { |
1765 | .compatible = "fsl,imx28-gpmi-nand", | 1778 | .compatible = "fsl,imx28-gpmi-nand", |
1766 | .data = (void *)&gpmi_devdata_imx28, | 1779 | .data = &gpmi_devdata_imx28, |
1767 | }, { | 1780 | }, { |
1768 | .compatible = "fsl,imx6q-gpmi-nand", | 1781 | .compatible = "fsl,imx6q-gpmi-nand", |
1769 | .data = (void *)&gpmi_devdata_imx6q, | 1782 | .data = &gpmi_devdata_imx6q, |
1770 | }, { | 1783 | }, { |
1771 | .compatible = "fsl,imx6sx-gpmi-nand", | 1784 | .compatible = "fsl,imx6sx-gpmi-nand", |
1772 | .data = (void *)&gpmi_devdata_imx6sx, | 1785 | .data = &gpmi_devdata_imx6sx, |
1773 | }, {} | 1786 | }, {} |
1774 | }; | 1787 | }; |
1775 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); | 1788 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); |
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index 687478c9f09c..7335346dc126 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c | |||
@@ -721,12 +721,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
721 | nand_chip->bbt_td = &lpc32xx_nand_bbt; | 721 | nand_chip->bbt_td = &lpc32xx_nand_bbt; |
722 | nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror; | 722 | nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror; |
723 | 723 | ||
724 | /* bitflip_threshold's default is defined as ecc_strength anyway. | ||
725 | * Unfortunately, it is set only later at add_mtd_device(). Meanwhile | ||
726 | * being 0, it causes bad block table scanning errors in | ||
727 | * nand_scan_tail(), so preparing it here. */ | ||
728 | mtd->bitflip_threshold = nand_chip->ecc.strength; | ||
729 | |||
730 | if (use_dma) { | 724 | if (use_dma) { |
731 | res = lpc32xx_dma_setup(host); | 725 | res = lpc32xx_dma_setup(host); |
732 | if (res) { | 726 | if (res) { |
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 53a6742e3da3..8caef28e0756 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c | |||
@@ -840,12 +840,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
840 | chip->ecc.strength = 1; | 840 | chip->ecc.strength = 1; |
841 | chip->ecc.hwctl = lpc32xx_nand_ecc_enable; | 841 | chip->ecc.hwctl = lpc32xx_nand_ecc_enable; |
842 | 842 | ||
843 | /* bitflip_threshold's default is defined as ecc_strength anyway. | ||
844 | * Unfortunately, it is set only later at add_mtd_device(). Meanwhile | ||
845 | * being 0, it causes bad block table scanning errors in | ||
846 | * nand_scan_tail(), so preparing it here already. */ | ||
847 | mtd->bitflip_threshold = chip->ecc.strength; | ||
848 | |||
849 | /* | 843 | /* |
850 | * Allocate a large enough buffer for a single huge page plus | 844 | * Allocate a large enough buffer for a single huge page plus |
851 | * extra space for the spare area and ECC storage area | 845 | * extra space for the spare area and ECC storage area |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4f3e80c68a26..d8cdf06343fb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -488,6 +488,23 @@ static int nand_check_wp(struct mtd_info *mtd) | |||
488 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad | 488 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad |
489 | * @mtd: MTD device structure | 489 | * @mtd: MTD device structure |
490 | * @ofs: offset from device start | 490 | * @ofs: offset from device start |
491 | * | ||
492 | * Check if the block is mark as reserved. | ||
493 | */ | ||
494 | static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) | ||
495 | { | ||
496 | struct nand_chip *chip = mtd->priv; | ||
497 | |||
498 | if (!chip->bbt) | ||
499 | return 0; | ||
500 | /* Return info from the table */ | ||
501 | return nand_isreserved_bbt(mtd, ofs); | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad | ||
506 | * @mtd: MTD device structure | ||
507 | * @ofs: offset from device start | ||
491 | * @getchip: 0, if the chip is already selected | 508 | * @getchip: 0, if the chip is already selected |
492 | * @allowbbt: 1, if its allowed to access the bbt area | 509 | * @allowbbt: 1, if its allowed to access the bbt area |
493 | * | 510 | * |
@@ -4113,6 +4130,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
4113 | mtd->_unlock = NULL; | 4130 | mtd->_unlock = NULL; |
4114 | mtd->_suspend = nand_suspend; | 4131 | mtd->_suspend = nand_suspend; |
4115 | mtd->_resume = nand_resume; | 4132 | mtd->_resume = nand_resume; |
4133 | mtd->_block_isreserved = nand_block_isreserved; | ||
4116 | mtd->_block_isbad = nand_block_isbad; | 4134 | mtd->_block_isbad = nand_block_isbad; |
4117 | mtd->_block_markbad = nand_block_markbad; | 4135 | mtd->_block_markbad = nand_block_markbad; |
4118 | mtd->writebufsize = mtd->writesize; | 4136 | mtd->writebufsize = mtd->writesize; |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 7f0c3b4c2a4f..443fa82cde6a 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -1311,6 +1311,20 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1311 | } | 1311 | } |
1312 | 1312 | ||
1313 | /** | 1313 | /** |
1314 | * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved | ||
1315 | * @mtd: MTD device structure | ||
1316 | * @offs: offset in the device | ||
1317 | */ | ||
1318 | int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs) | ||
1319 | { | ||
1320 | struct nand_chip *this = mtd->priv; | ||
1321 | int block; | ||
1322 | |||
1323 | block = (int)(offs >> this->bbt_erase_shift); | ||
1324 | return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED; | ||
1325 | } | ||
1326 | |||
1327 | /** | ||
1314 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad | 1328 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad |
1315 | * @mtd: MTD device structure | 1329 | * @mtd: MTD device structure |
1316 | * @offs: offset in the device | 1330 | * @offs: offset in the device |
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c new file mode 100644 index 000000000000..8b36253420fa --- /dev/null +++ b/drivers/mtd/nand/nand_timings.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Free Electrons | ||
3 | * | ||
4 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/export.h> | ||
14 | #include <linux/mtd/nand.h> | ||
15 | |||
16 | static const struct nand_sdr_timings onfi_sdr_timings[] = { | ||
17 | /* Mode 0 */ | ||
18 | { | ||
19 | .tADL_min = 200000, | ||
20 | .tALH_min = 20000, | ||
21 | .tALS_min = 50000, | ||
22 | .tAR_min = 25000, | ||
23 | .tCEA_max = 100000, | ||
24 | .tCEH_min = 20000, | ||
25 | .tCH_min = 20000, | ||
26 | .tCHZ_max = 100000, | ||
27 | .tCLH_min = 20000, | ||
28 | .tCLR_min = 20000, | ||
29 | .tCLS_min = 50000, | ||
30 | .tCOH_min = 0, | ||
31 | .tCS_min = 70000, | ||
32 | .tDH_min = 20000, | ||
33 | .tDS_min = 40000, | ||
34 | .tFEAT_max = 1000000, | ||
35 | .tIR_min = 10000, | ||
36 | .tITC_max = 1000000, | ||
37 | .tRC_min = 100000, | ||
38 | .tREA_max = 40000, | ||
39 | .tREH_min = 30000, | ||
40 | .tRHOH_min = 0, | ||
41 | .tRHW_min = 200000, | ||
42 | .tRHZ_max = 200000, | ||
43 | .tRLOH_min = 0, | ||
44 | .tRP_min = 50000, | ||
45 | .tRST_max = 250000000000, | ||
46 | .tWB_max = 200000, | ||
47 | .tRR_min = 40000, | ||
48 | .tWC_min = 100000, | ||
49 | .tWH_min = 30000, | ||
50 | .tWHR_min = 120000, | ||
51 | .tWP_min = 50000, | ||
52 | .tWW_min = 100000, | ||
53 | }, | ||
54 | /* Mode 1 */ | ||
55 | { | ||
56 | .tADL_min = 100000, | ||
57 | .tALH_min = 10000, | ||
58 | .tALS_min = 25000, | ||
59 | .tAR_min = 10000, | ||
60 | .tCEA_max = 45000, | ||
61 | .tCEH_min = 20000, | ||
62 | .tCH_min = 10000, | ||
63 | .tCHZ_max = 50000, | ||
64 | .tCLH_min = 10000, | ||
65 | .tCLR_min = 10000, | ||
66 | .tCLS_min = 25000, | ||
67 | .tCOH_min = 15000, | ||
68 | .tCS_min = 35000, | ||
69 | .tDH_min = 10000, | ||
70 | .tDS_min = 20000, | ||
71 | .tFEAT_max = 1000000, | ||
72 | .tIR_min = 0, | ||
73 | .tITC_max = 1000000, | ||
74 | .tRC_min = 50000, | ||
75 | .tREA_max = 30000, | ||
76 | .tREH_min = 15000, | ||
77 | .tRHOH_min = 15000, | ||
78 | .tRHW_min = 100000, | ||
79 | .tRHZ_max = 100000, | ||
80 | .tRLOH_min = 0, | ||
81 | .tRP_min = 25000, | ||
82 | .tRR_min = 20000, | ||
83 | .tRST_max = 500000000, | ||
84 | .tWB_max = 100000, | ||
85 | .tWC_min = 45000, | ||
86 | .tWH_min = 15000, | ||
87 | .tWHR_min = 80000, | ||
88 | .tWP_min = 25000, | ||
89 | .tWW_min = 100000, | ||
90 | }, | ||
91 | /* Mode 2 */ | ||
92 | { | ||
93 | .tADL_min = 100000, | ||
94 | .tALH_min = 10000, | ||
95 | .tALS_min = 15000, | ||
96 | .tAR_min = 10000, | ||
97 | .tCEA_max = 30000, | ||
98 | .tCEH_min = 20000, | ||
99 | .tCH_min = 10000, | ||
100 | .tCHZ_max = 50000, | ||
101 | .tCLH_min = 10000, | ||
102 | .tCLR_min = 10000, | ||
103 | .tCLS_min = 15000, | ||
104 | .tCOH_min = 15000, | ||
105 | .tCS_min = 25000, | ||
106 | .tDH_min = 5000, | ||
107 | .tDS_min = 15000, | ||
108 | .tFEAT_max = 1000000, | ||
109 | .tIR_min = 0, | ||
110 | .tITC_max = 1000000, | ||
111 | .tRC_min = 35000, | ||
112 | .tREA_max = 25000, | ||
113 | .tREH_min = 15000, | ||
114 | .tRHOH_min = 15000, | ||
115 | .tRHW_min = 100000, | ||
116 | .tRHZ_max = 100000, | ||
117 | .tRLOH_min = 0, | ||
118 | .tRR_min = 20000, | ||
119 | .tRST_max = 500000000, | ||
120 | .tWB_max = 100000, | ||
121 | .tRP_min = 17000, | ||
122 | .tWC_min = 35000, | ||
123 | .tWH_min = 15000, | ||
124 | .tWHR_min = 80000, | ||
125 | .tWP_min = 17000, | ||
126 | .tWW_min = 100000, | ||
127 | }, | ||
128 | /* Mode 3 */ | ||
129 | { | ||
130 | .tADL_min = 100000, | ||
131 | .tALH_min = 5000, | ||
132 | .tALS_min = 10000, | ||
133 | .tAR_min = 10000, | ||
134 | .tCEA_max = 25000, | ||
135 | .tCEH_min = 20000, | ||
136 | .tCH_min = 5000, | ||
137 | .tCHZ_max = 50000, | ||
138 | .tCLH_min = 5000, | ||
139 | .tCLR_min = 10000, | ||
140 | .tCLS_min = 10000, | ||
141 | .tCOH_min = 15000, | ||
142 | .tCS_min = 25000, | ||
143 | .tDH_min = 5000, | ||
144 | .tDS_min = 10000, | ||
145 | .tFEAT_max = 1000000, | ||
146 | .tIR_min = 0, | ||
147 | .tITC_max = 1000000, | ||
148 | .tRC_min = 30000, | ||
149 | .tREA_max = 20000, | ||
150 | .tREH_min = 10000, | ||
151 | .tRHOH_min = 15000, | ||
152 | .tRHW_min = 100000, | ||
153 | .tRHZ_max = 100000, | ||
154 | .tRLOH_min = 0, | ||
155 | .tRP_min = 15000, | ||
156 | .tRR_min = 20000, | ||
157 | .tRST_max = 500000000, | ||
158 | .tWB_max = 100000, | ||
159 | .tWC_min = 30000, | ||
160 | .tWH_min = 10000, | ||
161 | .tWHR_min = 80000, | ||
162 | .tWP_min = 15000, | ||
163 | .tWW_min = 100000, | ||
164 | }, | ||
165 | /* Mode 4 */ | ||
166 | { | ||
167 | .tADL_min = 70000, | ||
168 | .tALH_min = 5000, | ||
169 | .tALS_min = 10000, | ||
170 | .tAR_min = 10000, | ||
171 | .tCEA_max = 25000, | ||
172 | .tCEH_min = 20000, | ||
173 | .tCH_min = 5000, | ||
174 | .tCHZ_max = 30000, | ||
175 | .tCLH_min = 5000, | ||
176 | .tCLR_min = 10000, | ||
177 | .tCLS_min = 10000, | ||
178 | .tCOH_min = 15000, | ||
179 | .tCS_min = 20000, | ||
180 | .tDH_min = 5000, | ||
181 | .tDS_min = 10000, | ||
182 | .tFEAT_max = 1000000, | ||
183 | .tIR_min = 0, | ||
184 | .tITC_max = 1000000, | ||
185 | .tRC_min = 25000, | ||
186 | .tREA_max = 20000, | ||
187 | .tREH_min = 10000, | ||
188 | .tRHOH_min = 15000, | ||
189 | .tRHW_min = 100000, | ||
190 | .tRHZ_max = 100000, | ||
191 | .tRLOH_min = 5000, | ||
192 | .tRP_min = 12000, | ||
193 | .tRR_min = 20000, | ||
194 | .tRST_max = 500000000, | ||
195 | .tWB_max = 100000, | ||
196 | .tWC_min = 25000, | ||
197 | .tWH_min = 10000, | ||
198 | .tWHR_min = 80000, | ||
199 | .tWP_min = 12000, | ||
200 | .tWW_min = 100000, | ||
201 | }, | ||
202 | /* Mode 5 */ | ||
203 | { | ||
204 | .tADL_min = 70000, | ||
205 | .tALH_min = 5000, | ||
206 | .tALS_min = 10000, | ||
207 | .tAR_min = 10000, | ||
208 | .tCEA_max = 25000, | ||
209 | .tCEH_min = 20000, | ||
210 | .tCH_min = 5000, | ||
211 | .tCHZ_max = 30000, | ||
212 | .tCLH_min = 5000, | ||
213 | .tCLR_min = 10000, | ||
214 | .tCLS_min = 10000, | ||
215 | .tCOH_min = 15000, | ||
216 | .tCS_min = 15000, | ||
217 | .tDH_min = 5000, | ||
218 | .tDS_min = 7000, | ||
219 | .tFEAT_max = 1000000, | ||
220 | .tIR_min = 0, | ||
221 | .tITC_max = 1000000, | ||
222 | .tRC_min = 20000, | ||
223 | .tREA_max = 16000, | ||
224 | .tREH_min = 7000, | ||
225 | .tRHOH_min = 15000, | ||
226 | .tRHW_min = 100000, | ||
227 | .tRHZ_max = 100000, | ||
228 | .tRLOH_min = 5000, | ||
229 | .tRP_min = 10000, | ||
230 | .tRR_min = 20000, | ||
231 | .tRST_max = 500000000, | ||
232 | .tWB_max = 100000, | ||
233 | .tWC_min = 20000, | ||
234 | .tWH_min = 7000, | ||
235 | .tWHR_min = 80000, | ||
236 | .tWP_min = 10000, | ||
237 | .tWW_min = 100000, | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | /** | ||
242 | * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND | ||
243 | * timings according to the given ONFI timing mode | ||
244 | * @mode: ONFI timing mode | ||
245 | */ | ||
246 | const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode) | ||
247 | { | ||
248 | if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings)) | ||
249 | return ERR_PTR(-EINVAL); | ||
250 | |||
251 | return &onfi_sdr_timings[mode]; | ||
252 | } | ||
253 | EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings); | ||
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 79acbb8691b5..6b97bf17ce5d 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -208,10 +208,10 @@ static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info, | |||
208 | 208 | ||
209 | if (info->clk_state == CLOCK_ENABLE) { | 209 | if (info->clk_state == CLOCK_ENABLE) { |
210 | if (new_state != CLOCK_ENABLE) | 210 | if (new_state != CLOCK_ENABLE) |
211 | clk_disable(info->clk); | 211 | clk_disable_unprepare(info->clk); |
212 | } else { | 212 | } else { |
213 | if (new_state == CLOCK_ENABLE) | 213 | if (new_state == CLOCK_ENABLE) |
214 | clk_enable(info->clk); | 214 | clk_prepare_enable(info->clk); |
215 | } | 215 | } |
216 | 216 | ||
217 | info->clk_state = new_state; | 217 | info->clk_state = new_state; |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c713c8656710..b5ad6bebf5e7 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
@@ -48,6 +48,25 @@ static int read_sr(struct spi_nor *nor) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Read the flag status register, returning its value in the location | ||
52 | * Return the status register value. | ||
53 | * Returns negative if error occurred. | ||
54 | */ | ||
55 | static int read_fsr(struct spi_nor *nor) | ||
56 | { | ||
57 | int ret; | ||
58 | u8 val; | ||
59 | |||
60 | ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); | ||
61 | if (ret < 0) { | ||
62 | pr_err("error %d reading FSR\n", ret); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | return val; | ||
67 | } | ||
68 | |||
69 | /* | ||
51 | * Read configuration register, returning its value in the | 70 | * Read configuration register, returning its value in the |
52 | * location. Return the configuration register value. | 71 | * location. Return the configuration register value. |
53 | * Returns negative if error occured. | 72 | * Returns negative if error occured. |
@@ -165,6 +184,32 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor) | |||
165 | return -ETIMEDOUT; | 184 | return -ETIMEDOUT; |
166 | } | 185 | } |
167 | 186 | ||
187 | static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) | ||
188 | { | ||
189 | unsigned long deadline; | ||
190 | int sr; | ||
191 | int fsr; | ||
192 | |||
193 | deadline = jiffies + MAX_READY_WAIT_JIFFIES; | ||
194 | |||
195 | do { | ||
196 | cond_resched(); | ||
197 | |||
198 | sr = read_sr(nor); | ||
199 | if (sr < 0) { | ||
200 | break; | ||
201 | } else if (!(sr & SR_WIP)) { | ||
202 | fsr = read_fsr(nor); | ||
203 | if (fsr < 0) | ||
204 | break; | ||
205 | if (fsr & FSR_READY) | ||
206 | return 0; | ||
207 | } | ||
208 | } while (!time_after_eq(jiffies, deadline)); | ||
209 | |||
210 | return -ETIMEDOUT; | ||
211 | } | ||
212 | |||
168 | /* | 213 | /* |
169 | * Service routine to read status register until ready, or timeout occurs. | 214 | * Service routine to read status register until ready, or timeout occurs. |
170 | * Returns non-zero if error. | 215 | * Returns non-zero if error. |
@@ -402,6 +447,7 @@ struct flash_info { | |||
402 | #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ | 447 | #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ |
403 | #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ | 448 | #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ |
404 | #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ | 449 | #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ |
450 | #define USE_FSR 0x80 /* use flag status register */ | ||
405 | }; | 451 | }; |
406 | 452 | ||
407 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 453 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
@@ -449,6 +495,7 @@ const struct spi_device_id spi_nor_ids[] = { | |||
449 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | 495 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, |
450 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | 496 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, |
451 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, | 497 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, |
498 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, | ||
452 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, | 499 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, |
453 | 500 | ||
454 | /* ESMT */ | 501 | /* ESMT */ |
@@ -488,6 +535,8 @@ const struct spi_device_id spi_nor_ids[] = { | |||
488 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 535 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, |
489 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, | 536 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, |
490 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, | 537 | { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, |
538 | { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, | ||
539 | { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, | ||
491 | 540 | ||
492 | /* PMC */ | 541 | /* PMC */ |
493 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, | 542 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, |
@@ -965,6 +1014,10 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, | |||
965 | else | 1014 | else |
966 | mtd->_write = spi_nor_write; | 1015 | mtd->_write = spi_nor_write; |
967 | 1016 | ||
1017 | if ((info->flags & USE_FSR) && | ||
1018 | nor->wait_till_ready == spi_nor_wait_till_ready) | ||
1019 | nor->wait_till_ready = spi_nor_wait_till_fsr_ready; | ||
1020 | |||
968 | /* prefer "small sector" erase if possible */ | 1021 | /* prefer "small sector" erase if possible */ |
969 | if (info->flags & SECT_4K) { | 1022 | if (info->flags & SECT_4K) { |
970 | nor->erase_opcode = SPINOR_OP_BE_4K; | 1023 | nor->erase_opcode = SPINOR_OP_BE_4K; |
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 009ec0b5993d..2f7a3c090489 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
@@ -202,8 +202,7 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type) | |||
202 | } else { | 202 | } else { |
203 | acl = ERR_PTR(rc); | 203 | acl = ERR_PTR(rc); |
204 | } | 204 | } |
205 | if (value) | 205 | kfree(value); |
206 | kfree(value); | ||
207 | if (!IS_ERR(acl)) | 206 | if (!IS_ERR(acl)) |
208 | set_cached_acl(inode, type, acl); | 207 | set_cached_acl(inode, type, acl); |
209 | return acl; | 208 | return acl; |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index ad0f2e2a1700..d72817ac51f6 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -756,8 +756,7 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) | |||
756 | for (i=0; i < XATTRINDEX_HASHSIZE; i++) { | 756 | for (i=0; i < XATTRINDEX_HASHSIZE; i++) { |
757 | list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { | 757 | list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { |
758 | list_del(&xd->xindex); | 758 | list_del(&xd->xindex); |
759 | if (xd->xname) | 759 | kfree(xd->xname); |
760 | kfree(xd->xname); | ||
761 | jffs2_free_xattr_datum(xd); | 760 | jffs2_free_xattr_datum(xd); |
762 | } | 761 | } |
763 | } | 762 | } |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index a1b0b4c8fd79..031ff3a9a0bd 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -222,6 +222,7 @@ struct mtd_info { | |||
222 | int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 222 | int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
223 | int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 223 | int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
224 | int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | 224 | int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); |
225 | int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); | ||
225 | int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); | 226 | int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); |
226 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); | 227 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); |
227 | int (*_suspend) (struct mtd_info *mtd); | 228 | int (*_suspend) (struct mtd_info *mtd); |
@@ -302,6 +303,7 @@ static inline void mtd_sync(struct mtd_info *mtd) | |||
302 | int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 303 | int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
303 | int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 304 | int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
304 | int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 305 | int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
306 | int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs); | ||
305 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); | 307 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); |
306 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); | 308 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); |
307 | 309 | ||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2f0af2891f0f..3083c53e0270 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -810,6 +810,7 @@ extern struct nand_manufacturers nand_manuf_ids[]; | |||
810 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); | 810 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); |
811 | extern int nand_default_bbt(struct mtd_info *mtd); | 811 | extern int nand_default_bbt(struct mtd_info *mtd); |
812 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); | 812 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); |
813 | extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs); | ||
813 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); | 814 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); |
814 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 815 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
815 | int allowbbt); | 816 | int allowbbt); |
@@ -947,4 +948,56 @@ static inline int jedec_feature(struct nand_chip *chip) | |||
947 | return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features) | 948 | return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features) |
948 | : 0; | 949 | : 0; |
949 | } | 950 | } |
951 | |||
952 | /** | ||
953 | * struct nand_sdr_timings - SDR NAND chip timings | ||
954 | * | ||
955 | * This struct defines the timing requirements of a SDR NAND chip. | ||
956 | * These informations can be found in every NAND datasheets and the timings | ||
957 | * meaning are described in the ONFI specifications: | ||
958 | * www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing | ||
959 | * Parameters) | ||
960 | * | ||
961 | * All these timings are expressed in picoseconds. | ||
962 | */ | ||
963 | |||
964 | struct nand_sdr_timings { | ||
965 | u32 tALH_min; | ||
966 | u32 tADL_min; | ||
967 | u32 tALS_min; | ||
968 | u32 tAR_min; | ||
969 | u32 tCEA_max; | ||
970 | u32 tCEH_min; | ||
971 | u32 tCH_min; | ||
972 | u32 tCHZ_max; | ||
973 | u32 tCLH_min; | ||
974 | u32 tCLR_min; | ||
975 | u32 tCLS_min; | ||
976 | u32 tCOH_min; | ||
977 | u32 tCS_min; | ||
978 | u32 tDH_min; | ||
979 | u32 tDS_min; | ||
980 | u32 tFEAT_max; | ||
981 | u32 tIR_min; | ||
982 | u32 tITC_max; | ||
983 | u32 tRC_min; | ||
984 | u32 tREA_max; | ||
985 | u32 tREH_min; | ||
986 | u32 tRHOH_min; | ||
987 | u32 tRHW_min; | ||
988 | u32 tRHZ_max; | ||
989 | u32 tRLOH_min; | ||
990 | u32 tRP_min; | ||
991 | u32 tRR_min; | ||
992 | u64 tRST_max; | ||
993 | u32 tWB_max; | ||
994 | u32 tWC_min; | ||
995 | u32 tWH_min; | ||
996 | u32 tWHR_min; | ||
997 | u32 tWP_min; | ||
998 | u32 tWW_min; | ||
999 | }; | ||
1000 | |||
1001 | /* get timing characteristics from ONFI timing mode. */ | ||
1002 | const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode); | ||
950 | #endif /* __LINUX_MTD_NAND_H */ | 1003 | #endif /* __LINUX_MTD_NAND_H */ |
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 53241842a7ab..9e6294f32ba8 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ | 34 | #define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ |
35 | #define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ | 35 | #define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ |
36 | #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ | 36 | #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ |
37 | #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ | ||
37 | 38 | ||
38 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ | 39 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ |
39 | #define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ | 40 | #define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ |
@@ -66,6 +67,9 @@ | |||
66 | 67 | ||
67 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ | 68 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ |
68 | 69 | ||
70 | /* Flag Status Register bits */ | ||
71 | #define FSR_READY 0x80 | ||
72 | |||
69 | /* Configuration Register bits. */ | 73 | /* Configuration Register bits. */ |
70 | #define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ | 74 | #define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ |
71 | 75 | ||