diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/mtd/chips | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r-- | drivers/mtd/chips/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 112 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 192 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0020.c | 2 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_probe.c | 2 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_util.c | 11 | ||||
-rw-r--r-- | drivers/mtd/chips/fwh_lock.h | 2 | ||||
-rw-r--r-- | drivers/mtd/chips/jedec_probe.c | 37 |
8 files changed, 191 insertions, 169 deletions
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 35c6a23b183b..b1e3c26edd6d 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -19,7 +19,7 @@ config MTD_JEDECPROBE | |||
19 | help | 19 | help |
20 | This option enables JEDEC-style probing of flash chips which are not | 20 | This option enables JEDEC-style probing of flash chips which are not |
21 | compatible with the Common Flash Interface, but will use the common | 21 | compatible with the Common Flash Interface, but will use the common |
22 | CFI-targetted flash drivers for any chips which are identified which | 22 | CFI-targeted flash drivers for any chips which are identified which |
23 | are in fact compatible in all but the probe method. This actually | 23 | are in fact compatible in all but the probe method. This actually |
24 | covers most AMD/Fujitsu-compatible chips and also non-CFI | 24 | covers most AMD/Fujitsu-compatible chips and also non-CFI |
25 | Intel chips. | 25 | Intel chips. |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 9e2b7e9e0ad9..e1e122f2f929 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -162,7 +162,7 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) | |||
162 | #endif | 162 | #endif |
163 | 163 | ||
164 | /* Atmel chips don't use the same PRI format as Intel chips */ | 164 | /* Atmel chips don't use the same PRI format as Intel chips */ |
165 | static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | 165 | static void fixup_convert_atmel_pri(struct mtd_info *mtd) |
166 | { | 166 | { |
167 | struct map_info *map = mtd->priv; | 167 | struct map_info *map = mtd->priv; |
168 | struct cfi_private *cfi = map->fldrv_priv; | 168 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -202,7 +202,7 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | |||
202 | cfi->cfiq->BufWriteTimeoutMax = 0; | 202 | cfi->cfiq->BufWriteTimeoutMax = 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param) | 205 | static void fixup_at49bv640dx_lock(struct mtd_info *mtd) |
206 | { | 206 | { |
207 | struct map_info *map = mtd->priv; | 207 | struct map_info *map = mtd->priv; |
208 | struct cfi_private *cfi = map->fldrv_priv; | 208 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -214,7 +214,7 @@ static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param) | |||
214 | 214 | ||
215 | #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE | 215 | #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE |
216 | /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ | 216 | /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ |
217 | static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) | 217 | static void fixup_intel_strataflash(struct mtd_info *mtd) |
218 | { | 218 | { |
219 | struct map_info *map = mtd->priv; | 219 | struct map_info *map = mtd->priv; |
220 | struct cfi_private *cfi = map->fldrv_priv; | 220 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -227,7 +227,7 @@ static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) | |||
227 | #endif | 227 | #endif |
228 | 228 | ||
229 | #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND | 229 | #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND |
230 | static void fixup_no_write_suspend(struct mtd_info *mtd, void* param) | 230 | static void fixup_no_write_suspend(struct mtd_info *mtd) |
231 | { | 231 | { |
232 | struct map_info *map = mtd->priv; | 232 | struct map_info *map = mtd->priv; |
233 | struct cfi_private *cfi = map->fldrv_priv; | 233 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -240,7 +240,7 @@ static void fixup_no_write_suspend(struct mtd_info *mtd, void* param) | |||
240 | } | 240 | } |
241 | #endif | 241 | #endif |
242 | 242 | ||
243 | static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) | 243 | static void fixup_st_m28w320ct(struct mtd_info *mtd) |
244 | { | 244 | { |
245 | struct map_info *map = mtd->priv; | 245 | struct map_info *map = mtd->priv; |
246 | struct cfi_private *cfi = map->fldrv_priv; | 246 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -249,7 +249,7 @@ static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) | |||
249 | cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ | 249 | cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ |
250 | } | 250 | } |
251 | 251 | ||
252 | static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param) | 252 | static void fixup_st_m28w320cb(struct mtd_info *mtd) |
253 | { | 253 | { |
254 | struct map_info *map = mtd->priv; | 254 | struct map_info *map = mtd->priv; |
255 | struct cfi_private *cfi = map->fldrv_priv; | 255 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -259,7 +259,7 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param) | |||
259 | (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; | 259 | (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; |
260 | }; | 260 | }; |
261 | 261 | ||
262 | static void fixup_use_point(struct mtd_info *mtd, void *param) | 262 | static void fixup_use_point(struct mtd_info *mtd) |
263 | { | 263 | { |
264 | struct map_info *map = mtd->priv; | 264 | struct map_info *map = mtd->priv; |
265 | if (!mtd->point && map_is_linear(map)) { | 265 | if (!mtd->point && map_is_linear(map)) { |
@@ -268,7 +268,7 @@ static void fixup_use_point(struct mtd_info *mtd, void *param) | |||
268 | } | 268 | } |
269 | } | 269 | } |
270 | 270 | ||
271 | static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) | 271 | static void fixup_use_write_buffers(struct mtd_info *mtd) |
272 | { | 272 | { |
273 | struct map_info *map = mtd->priv; | 273 | struct map_info *map = mtd->priv; |
274 | struct cfi_private *cfi = map->fldrv_priv; | 274 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -282,7 +282,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) | |||
282 | /* | 282 | /* |
283 | * Some chips power-up with all sectors locked by default. | 283 | * Some chips power-up with all sectors locked by default. |
284 | */ | 284 | */ |
285 | static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param) | 285 | static void fixup_unlock_powerup_lock(struct mtd_info *mtd) |
286 | { | 286 | { |
287 | struct map_info *map = mtd->priv; | 287 | struct map_info *map = mtd->priv; |
288 | struct cfi_private *cfi = map->fldrv_priv; | 288 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -295,31 +295,31 @@ static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param) | |||
295 | } | 295 | } |
296 | 296 | ||
297 | static struct cfi_fixup cfi_fixup_table[] = { | 297 | static struct cfi_fixup cfi_fixup_table[] = { |
298 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, | 298 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri }, |
299 | { CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock, NULL }, | 299 | { CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock }, |
300 | { CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock, NULL }, | 300 | { CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock }, |
301 | #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE | 301 | #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE |
302 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, | 302 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash }, |
303 | #endif | 303 | #endif |
304 | #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND | 304 | #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND |
305 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL }, | 305 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend }, |
306 | #endif | 306 | #endif |
307 | #if !FORCE_WORD_WRITE | 307 | #if !FORCE_WORD_WRITE |
308 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL }, | 308 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers }, |
309 | #endif | 309 | #endif |
310 | { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL }, | 310 | { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct }, |
311 | { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL }, | 311 | { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb }, |
312 | { CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, }, | 312 | { CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock }, |
313 | { 0, 0, NULL, NULL } | 313 | { 0, 0, NULL } |
314 | }; | 314 | }; |
315 | 315 | ||
316 | static struct cfi_fixup jedec_fixup_table[] = { | 316 | static struct cfi_fixup jedec_fixup_table[] = { |
317 | { CFI_MFR_INTEL, I82802AB, fixup_use_fwh_lock, NULL, }, | 317 | { CFI_MFR_INTEL, I82802AB, fixup_use_fwh_lock }, |
318 | { CFI_MFR_INTEL, I82802AC, fixup_use_fwh_lock, NULL, }, | 318 | { CFI_MFR_INTEL, I82802AC, fixup_use_fwh_lock }, |
319 | { CFI_MFR_ST, M50LPW080, fixup_use_fwh_lock, NULL, }, | 319 | { CFI_MFR_ST, M50LPW080, fixup_use_fwh_lock }, |
320 | { CFI_MFR_ST, M50FLW080A, fixup_use_fwh_lock, NULL, }, | 320 | { CFI_MFR_ST, M50FLW080A, fixup_use_fwh_lock }, |
321 | { CFI_MFR_ST, M50FLW080B, fixup_use_fwh_lock, NULL, }, | 321 | { CFI_MFR_ST, M50FLW080B, fixup_use_fwh_lock }, |
322 | { 0, 0, NULL, NULL } | 322 | { 0, 0, NULL } |
323 | }; | 323 | }; |
324 | static struct cfi_fixup fixup_table[] = { | 324 | static struct cfi_fixup fixup_table[] = { |
325 | /* The CFI vendor ids and the JEDEC vendor IDs appear | 325 | /* The CFI vendor ids and the JEDEC vendor IDs appear |
@@ -327,8 +327,8 @@ static struct cfi_fixup fixup_table[] = { | |||
327 | * well. This table is to pick all cases where | 327 | * well. This table is to pick all cases where |
328 | * we know that is the case. | 328 | * we know that is the case. |
329 | */ | 329 | */ |
330 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL }, | 330 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point }, |
331 | { 0, 0, NULL, NULL } | 331 | { 0, 0, NULL } |
332 | }; | 332 | }; |
333 | 333 | ||
334 | static void cfi_fixup_major_minor(struct cfi_private *cfi, | 334 | static void cfi_fixup_major_minor(struct cfi_private *cfi, |
@@ -455,6 +455,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
455 | mtd->flags = MTD_CAP_NORFLASH; | 455 | mtd->flags = MTD_CAP_NORFLASH; |
456 | mtd->name = map->name; | 456 | mtd->name = map->name; |
457 | mtd->writesize = 1; | 457 | mtd->writesize = 1; |
458 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | ||
458 | 459 | ||
459 | mtd->reboot_notifier.notifier_call = cfi_intelext_reboot; | 460 | mtd->reboot_notifier.notifier_call = cfi_intelext_reboot; |
460 | 461 | ||
@@ -811,12 +812,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long | |||
811 | break; | 812 | break; |
812 | 813 | ||
813 | if (time_after(jiffies, timeo)) { | 814 | if (time_after(jiffies, timeo)) { |
814 | /* Urgh. Resume and pretend we weren't here. */ | 815 | /* Urgh. Resume and pretend we weren't here. |
815 | map_write(map, CMD(0xd0), adr); | 816 | * Make sure we're in 'read status' mode if it had finished */ |
816 | /* Make sure we're in 'read status' mode if it had finished */ | 817 | put_chip(map, chip, adr); |
817 | map_write(map, CMD(0x70), adr); | ||
818 | chip->state = FL_ERASING; | ||
819 | chip->oldstate = FL_READY; | ||
820 | printk(KERN_ERR "%s: Chip not ready after erase " | 818 | printk(KERN_ERR "%s: Chip not ready after erase " |
821 | "suspended: status = 0x%lx\n", map->name, status.x[0]); | 819 | "suspended: status = 0x%lx\n", map->name, status.x[0]); |
822 | return -EIO; | 820 | return -EIO; |
@@ -996,7 +994,6 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
996 | 994 | ||
997 | switch(chip->oldstate) { | 995 | switch(chip->oldstate) { |
998 | case FL_ERASING: | 996 | case FL_ERASING: |
999 | chip->state = chip->oldstate; | ||
1000 | /* What if one interleaved chip has finished and the | 997 | /* What if one interleaved chip has finished and the |
1001 | other hasn't? The old code would leave the finished | 998 | other hasn't? The old code would leave the finished |
1002 | one in READY mode. That's bad, and caused -EROFS | 999 | one in READY mode. That's bad, and caused -EROFS |
@@ -1229,10 +1226,32 @@ static int inval_cache_and_wait_for_operation( | |||
1229 | sleep_time = chip_op_time / 2; | 1226 | sleep_time = chip_op_time / 2; |
1230 | 1227 | ||
1231 | for (;;) { | 1228 | for (;;) { |
1229 | if (chip->state != chip_state) { | ||
1230 | /* Someone's suspended the operation: sleep */ | ||
1231 | DECLARE_WAITQUEUE(wait, current); | ||
1232 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1233 | add_wait_queue(&chip->wq, &wait); | ||
1234 | mutex_unlock(&chip->mutex); | ||
1235 | schedule(); | ||
1236 | remove_wait_queue(&chip->wq, &wait); | ||
1237 | mutex_lock(&chip->mutex); | ||
1238 | continue; | ||
1239 | } | ||
1240 | |||
1232 | status = map_read(map, cmd_adr); | 1241 | status = map_read(map, cmd_adr); |
1233 | if (map_word_andequal(map, status, status_OK, status_OK)) | 1242 | if (map_word_andequal(map, status, status_OK, status_OK)) |
1234 | break; | 1243 | break; |
1235 | 1244 | ||
1245 | if (chip->erase_suspended && chip_state == FL_ERASING) { | ||
1246 | /* Erase suspend occurred while sleep: reset timeout */ | ||
1247 | timeo = reset_timeo; | ||
1248 | chip->erase_suspended = 0; | ||
1249 | } | ||
1250 | if (chip->write_suspended && chip_state == FL_WRITING) { | ||
1251 | /* Write suspend occurred while sleep: reset timeout */ | ||
1252 | timeo = reset_timeo; | ||
1253 | chip->write_suspended = 0; | ||
1254 | } | ||
1236 | if (!timeo) { | 1255 | if (!timeo) { |
1237 | map_write(map, CMD(0x70), cmd_adr); | 1256 | map_write(map, CMD(0x70), cmd_adr); |
1238 | chip->state = FL_STATUS; | 1257 | chip->state = FL_STATUS; |
@@ -1256,27 +1275,6 @@ static int inval_cache_and_wait_for_operation( | |||
1256 | timeo--; | 1275 | timeo--; |
1257 | } | 1276 | } |
1258 | mutex_lock(&chip->mutex); | 1277 | mutex_lock(&chip->mutex); |
1259 | |||
1260 | while (chip->state != chip_state) { | ||
1261 | /* Someone's suspended the operation: sleep */ | ||
1262 | DECLARE_WAITQUEUE(wait, current); | ||
1263 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1264 | add_wait_queue(&chip->wq, &wait); | ||
1265 | mutex_unlock(&chip->mutex); | ||
1266 | schedule(); | ||
1267 | remove_wait_queue(&chip->wq, &wait); | ||
1268 | mutex_lock(&chip->mutex); | ||
1269 | } | ||
1270 | if (chip->erase_suspended && chip_state == FL_ERASING) { | ||
1271 | /* Erase suspend occured while sleep: reset timeout */ | ||
1272 | timeo = reset_timeo; | ||
1273 | chip->erase_suspended = 0; | ||
1274 | } | ||
1275 | if (chip->write_suspended && chip_state == FL_WRITING) { | ||
1276 | /* Write suspend occured while sleep: reset timeout */ | ||
1277 | timeo = reset_timeo; | ||
1278 | chip->write_suspended = 0; | ||
1279 | } | ||
1280 | } | 1278 | } |
1281 | 1279 | ||
1282 | /* Done and happy. */ | 1280 | /* Done and happy. */ |
@@ -1496,7 +1494,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1496 | 1494 | ||
1497 | switch (mode) { | 1495 | switch (mode) { |
1498 | case FL_WRITING: | 1496 | case FL_WRITING: |
1499 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); | 1497 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41); |
1500 | break; | 1498 | break; |
1501 | case FL_OTP_WRITE: | 1499 | case FL_OTP_WRITE: |
1502 | write_cmd = CMD(0xc0); | 1500 | write_cmd = CMD(0xc0); |
@@ -1661,7 +1659,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1661 | cmd_adr = adr & ~(wbufsize-1); | 1659 | cmd_adr = adr & ~(wbufsize-1); |
1662 | 1660 | ||
1663 | /* Let's determine this according to the interleave only once */ | 1661 | /* Let's determine this according to the interleave only once */ |
1664 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); | 1662 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9); |
1665 | 1663 | ||
1666 | mutex_lock(&chip->mutex); | 1664 | mutex_lock(&chip->mutex); |
1667 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); | 1665 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 3e6c47bdce53..23175edd5634 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -134,7 +134,7 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) | |||
134 | 134 | ||
135 | #ifdef AMD_BOOTLOC_BUG | 135 | #ifdef AMD_BOOTLOC_BUG |
136 | /* Wheee. Bring me the head of someone at AMD. */ | 136 | /* Wheee. Bring me the head of someone at AMD. */ |
137 | static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) | 137 | static void fixup_amd_bootblock(struct mtd_info *mtd) |
138 | { | 138 | { |
139 | struct map_info *map = mtd->priv; | 139 | struct map_info *map = mtd->priv; |
140 | struct cfi_private *cfi = map->fldrv_priv; | 140 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -186,7 +186,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) | |||
186 | } | 186 | } |
187 | #endif | 187 | #endif |
188 | 188 | ||
189 | static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) | 189 | static void fixup_use_write_buffers(struct mtd_info *mtd) |
190 | { | 190 | { |
191 | struct map_info *map = mtd->priv; | 191 | struct map_info *map = mtd->priv; |
192 | struct cfi_private *cfi = map->fldrv_priv; | 192 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -197,7 +197,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* Atmel chips don't use the same PRI format as AMD chips */ | 199 | /* Atmel chips don't use the same PRI format as AMD chips */ |
200 | static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | 200 | static void fixup_convert_atmel_pri(struct mtd_info *mtd) |
201 | { | 201 | { |
202 | struct map_info *map = mtd->priv; | 202 | struct map_info *map = mtd->priv; |
203 | struct cfi_private *cfi = map->fldrv_priv; | 203 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -228,14 +228,14 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | |||
228 | cfi->cfiq->BufWriteTimeoutMax = 0; | 228 | cfi->cfiq->BufWriteTimeoutMax = 0; |
229 | } | 229 | } |
230 | 230 | ||
231 | static void fixup_use_secsi(struct mtd_info *mtd, void *param) | 231 | static void fixup_use_secsi(struct mtd_info *mtd) |
232 | { | 232 | { |
233 | /* Setup for chips with a secsi area */ | 233 | /* Setup for chips with a secsi area */ |
234 | mtd->read_user_prot_reg = cfi_amdstd_secsi_read; | 234 | mtd->read_user_prot_reg = cfi_amdstd_secsi_read; |
235 | mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; | 235 | mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; |
236 | } | 236 | } |
237 | 237 | ||
238 | static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) | 238 | static void fixup_use_erase_chip(struct mtd_info *mtd) |
239 | { | 239 | { |
240 | struct map_info *map = mtd->priv; | 240 | struct map_info *map = mtd->priv; |
241 | struct cfi_private *cfi = map->fldrv_priv; | 241 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -250,7 +250,7 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) | |||
250 | * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors | 250 | * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors |
251 | * locked by default. | 251 | * locked by default. |
252 | */ | 252 | */ |
253 | static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) | 253 | static void fixup_use_atmel_lock(struct mtd_info *mtd) |
254 | { | 254 | { |
255 | mtd->lock = cfi_atmel_lock; | 255 | mtd->lock = cfi_atmel_lock; |
256 | mtd->unlock = cfi_atmel_unlock; | 256 | mtd->unlock = cfi_atmel_unlock; |
@@ -263,7 +263,7 @@ static void fixup_old_sst_eraseregion(struct mtd_info *mtd) | |||
263 | struct cfi_private *cfi = map->fldrv_priv; | 263 | struct cfi_private *cfi = map->fldrv_priv; |
264 | 264 | ||
265 | /* | 265 | /* |
266 | * These flashes report two seperate eraseblock regions based on the | 266 | * These flashes report two separate eraseblock regions based on the |
267 | * sector_erase-size and block_erase-size, although they both operate on the | 267 | * sector_erase-size and block_erase-size, although they both operate on the |
268 | * same memory. This is not allowed according to CFI, so we just pick the | 268 | * same memory. This is not allowed according to CFI, so we just pick the |
269 | * sector_erase-size. | 269 | * sector_erase-size. |
@@ -271,7 +271,7 @@ static void fixup_old_sst_eraseregion(struct mtd_info *mtd) | |||
271 | cfi->cfiq->NumEraseRegions = 1; | 271 | cfi->cfiq->NumEraseRegions = 1; |
272 | } | 272 | } |
273 | 273 | ||
274 | static void fixup_sst39vf(struct mtd_info *mtd, void *param) | 274 | static void fixup_sst39vf(struct mtd_info *mtd) |
275 | { | 275 | { |
276 | struct map_info *map = mtd->priv; | 276 | struct map_info *map = mtd->priv; |
277 | struct cfi_private *cfi = map->fldrv_priv; | 277 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -282,7 +282,7 @@ static void fixup_sst39vf(struct mtd_info *mtd, void *param) | |||
282 | cfi->addr_unlock2 = 0x2AAA; | 282 | cfi->addr_unlock2 = 0x2AAA; |
283 | } | 283 | } |
284 | 284 | ||
285 | static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) | 285 | static void fixup_sst39vf_rev_b(struct mtd_info *mtd) |
286 | { | 286 | { |
287 | struct map_info *map = mtd->priv; | 287 | struct map_info *map = mtd->priv; |
288 | struct cfi_private *cfi = map->fldrv_priv; | 288 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -291,9 +291,26 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) | |||
291 | 291 | ||
292 | cfi->addr_unlock1 = 0x555; | 292 | cfi->addr_unlock1 = 0x555; |
293 | cfi->addr_unlock2 = 0x2AA; | 293 | cfi->addr_unlock2 = 0x2AA; |
294 | |||
295 | cfi->sector_erase_cmd = CMD(0x50); | ||
296 | } | ||
297 | |||
298 | static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd) | ||
299 | { | ||
300 | struct map_info *map = mtd->priv; | ||
301 | struct cfi_private *cfi = map->fldrv_priv; | ||
302 | |||
303 | fixup_sst39vf_rev_b(mtd); | ||
304 | |||
305 | /* | ||
306 | * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where | ||
307 | * it should report a size of 8KBytes (0x0020*256). | ||
308 | */ | ||
309 | cfi->cfiq->EraseRegionInfo[0] = 0x002003ff; | ||
310 | pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name); | ||
294 | } | 311 | } |
295 | 312 | ||
296 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) | 313 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd) |
297 | { | 314 | { |
298 | struct map_info *map = mtd->priv; | 315 | struct map_info *map = mtd->priv; |
299 | struct cfi_private *cfi = map->fldrv_priv; | 316 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -304,7 +321,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) | |||
304 | } | 321 | } |
305 | } | 322 | } |
306 | 323 | ||
307 | static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param) | 324 | static void fixup_s29gl032n_sectors(struct mtd_info *mtd) |
308 | { | 325 | { |
309 | struct map_info *map = mtd->priv; | 326 | struct map_info *map = mtd->priv; |
310 | struct cfi_private *cfi = map->fldrv_priv; | 327 | struct cfi_private *cfi = map->fldrv_priv; |
@@ -317,43 +334,48 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param) | |||
317 | 334 | ||
318 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ | 335 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ |
319 | static struct cfi_fixup cfi_nopri_fixup_table[] = { | 336 | static struct cfi_fixup cfi_nopri_fixup_table[] = { |
320 | { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602 | 337 | { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ |
321 | { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601 | 338 | { CFI_MFR_SST, 0x234b, fixup_sst39vf }, /* SST39VF1601 */ |
322 | { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202 | 339 | { CFI_MFR_SST, 0x235a, fixup_sst39vf }, /* SST39VF3202 */ |
323 | { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201 | 340 | { CFI_MFR_SST, 0x235b, fixup_sst39vf }, /* SST39VF3201 */ |
324 | { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B | 341 | { CFI_MFR_SST, 0x235c, fixup_sst39vf_rev_b }, /* SST39VF3202B */ |
325 | { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B | 342 | { CFI_MFR_SST, 0x235d, fixup_sst39vf_rev_b }, /* SST39VF3201B */ |
326 | { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B | 343 | { CFI_MFR_SST, 0x236c, fixup_sst39vf_rev_b }, /* SST39VF6402B */ |
327 | { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B | 344 | { CFI_MFR_SST, 0x236d, fixup_sst39vf_rev_b }, /* SST39VF6401B */ |
328 | { 0, 0, NULL, NULL } | 345 | { 0, 0, NULL } |
329 | }; | 346 | }; |
330 | 347 | ||
331 | static struct cfi_fixup cfi_fixup_table[] = { | 348 | static struct cfi_fixup cfi_fixup_table[] = { |
332 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, | 349 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri }, |
333 | #ifdef AMD_BOOTLOC_BUG | 350 | #ifdef AMD_BOOTLOC_BUG |
334 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | 351 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock }, |
335 | { CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | 352 | { CFI_MFR_AMIC, CFI_ID_ANY, fixup_amd_bootblock }, |
353 | { CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock }, | ||
336 | #endif | 354 | #endif |
337 | { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, | 355 | { CFI_MFR_AMD, 0x0050, fixup_use_secsi }, |
338 | { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, }, | 356 | { CFI_MFR_AMD, 0x0053, fixup_use_secsi }, |
339 | { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, }, | 357 | { CFI_MFR_AMD, 0x0055, fixup_use_secsi }, |
340 | { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, | 358 | { CFI_MFR_AMD, 0x0056, fixup_use_secsi }, |
341 | { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, | 359 | { CFI_MFR_AMD, 0x005C, fixup_use_secsi }, |
342 | { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, | 360 | { CFI_MFR_AMD, 0x005F, fixup_use_secsi }, |
343 | { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, }, | 361 | { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors }, |
344 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, | 362 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, |
345 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, | 363 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, |
346 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, | 364 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, |
365 | { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ | ||
366 | { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ | ||
367 | { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ | ||
368 | { CFI_MFR_SST, 0x536d, fixup_sst38vf640x_sectorsize }, /* SST38VF6403 */ | ||
347 | #if !FORCE_WORD_WRITE | 369 | #if !FORCE_WORD_WRITE |
348 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, | 370 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers }, |
349 | #endif | 371 | #endif |
350 | { 0, 0, NULL, NULL } | 372 | { 0, 0, NULL } |
351 | }; | 373 | }; |
352 | static struct cfi_fixup jedec_fixup_table[] = { | 374 | static struct cfi_fixup jedec_fixup_table[] = { |
353 | { CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, | 375 | { CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock }, |
354 | { CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock, NULL, }, | 376 | { CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock }, |
355 | { CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, | 377 | { CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock }, |
356 | { 0, 0, NULL, NULL } | 378 | { 0, 0, NULL } |
357 | }; | 379 | }; |
358 | 380 | ||
359 | static struct cfi_fixup fixup_table[] = { | 381 | static struct cfi_fixup fixup_table[] = { |
@@ -362,18 +384,37 @@ static struct cfi_fixup fixup_table[] = { | |||
362 | * well. This table is to pick all cases where | 384 | * well. This table is to pick all cases where |
363 | * we know that is the case. | 385 | * we know that is the case. |
364 | */ | 386 | */ |
365 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, | 387 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip }, |
366 | { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, | 388 | { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock }, |
367 | { 0, 0, NULL, NULL } | 389 | { 0, 0, NULL } |
368 | }; | 390 | }; |
369 | 391 | ||
370 | 392 | ||
371 | static void cfi_fixup_major_minor(struct cfi_private *cfi, | 393 | static void cfi_fixup_major_minor(struct cfi_private *cfi, |
372 | struct cfi_pri_amdstd *extp) | 394 | struct cfi_pri_amdstd *extp) |
373 | { | 395 | { |
374 | if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && | 396 | if (cfi->mfr == CFI_MFR_SAMSUNG) { |
375 | extp->MajorVersion == '0') | 397 | if ((extp->MajorVersion == '0' && extp->MinorVersion == '0') || |
398 | (extp->MajorVersion == '3' && extp->MinorVersion == '3')) { | ||
399 | /* | ||
400 | * Samsung K8P2815UQB and K8D6x16UxM chips | ||
401 | * report major=0 / minor=0. | ||
402 | * K8D3x16UxC chips report major=3 / minor=3. | ||
403 | */ | ||
404 | printk(KERN_NOTICE " Fixing Samsung's Amd/Fujitsu" | ||
405 | " Extended Query version to 1.%c\n", | ||
406 | extp->MinorVersion); | ||
407 | extp->MajorVersion = '1'; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * SST 38VF640x chips report major=0xFF / minor=0xFF. | ||
413 | */ | ||
414 | if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) { | ||
376 | extp->MajorVersion = '1'; | 415 | extp->MajorVersion = '1'; |
416 | extp->MinorVersion = '0'; | ||
417 | } | ||
377 | } | 418 | } |
378 | 419 | ||
379 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | 420 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) |
@@ -400,6 +441,10 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
400 | mtd->flags = MTD_CAP_NORFLASH; | 441 | mtd->flags = MTD_CAP_NORFLASH; |
401 | mtd->name = map->name; | 442 | mtd->name = map->name; |
402 | mtd->writesize = 1; | 443 | mtd->writesize = 1; |
444 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | ||
445 | |||
446 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n", | ||
447 | __func__, mtd->writebufsize); | ||
403 | 448 | ||
404 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; | 449 | mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; |
405 | 450 | ||
@@ -417,13 +462,14 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
417 | cfi_fixup_major_minor(cfi, extp); | 462 | cfi_fixup_major_minor(cfi, extp); |
418 | 463 | ||
419 | /* | 464 | /* |
420 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4 | 465 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 |
421 | * see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19 | 466 | * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 |
422 | * http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf | 467 | * http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf |
423 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf | 468 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf |
469 | * http://www.spansion.com/Support/Datasheets/S29GL_128S_01GS_00_02_e.pdf | ||
424 | */ | 470 | */ |
425 | if (extp->MajorVersion != '1' || | 471 | if (extp->MajorVersion != '1' || |
426 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) { | 472 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '5'))) { |
427 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " | 473 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " |
428 | "version %c.%c (%#02x/%#02x).\n", | 474 | "version %c.%c (%#02x/%#02x).\n", |
429 | extp->MajorVersion, extp->MinorVersion, | 475 | extp->MajorVersion, extp->MinorVersion, |
@@ -545,15 +591,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) | |||
545 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); | 591 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); |
546 | goto setup_err; | 592 | goto setup_err; |
547 | } | 593 | } |
548 | #if 0 | ||
549 | // debug | ||
550 | for (i=0; i<mtd->numeraseregions;i++){ | ||
551 | printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", | ||
552 | i,mtd->eraseregions[i].offset, | ||
553 | mtd->eraseregions[i].erasesize, | ||
554 | mtd->eraseregions[i].numblocks); | ||
555 | } | ||
556 | #endif | ||
557 | 594 | ||
558 | __module_get(THIS_MODULE); | 595 | __module_get(THIS_MODULE); |
559 | register_reboot_notifier(&mtd->reboot_notifier); | 596 | register_reboot_notifier(&mtd->reboot_notifier); |
@@ -575,8 +612,8 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) | |||
575 | * | 612 | * |
576 | * Note that anything more complicated than checking if no bits are toggling | 613 | * Note that anything more complicated than checking if no bits are toggling |
577 | * (including checking DQ5 for an error status) is tricky to get working | 614 | * (including checking DQ5 for an error status) is tricky to get working |
578 | * correctly and is therefore not done (particulary with interleaved chips | 615 | * correctly and is therefore not done (particularly with interleaved chips |
579 | * as each chip must be checked independantly of the others). | 616 | * as each chip must be checked independently of the others). |
580 | */ | 617 | */ |
581 | static int __xipram chip_ready(struct map_info *map, unsigned long addr) | 618 | static int __xipram chip_ready(struct map_info *map, unsigned long addr) |
582 | { | 619 | { |
@@ -599,8 +636,8 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr) | |||
599 | * | 636 | * |
600 | * Note that anything more complicated than checking if no bits are toggling | 637 | * Note that anything more complicated than checking if no bits are toggling |
601 | * (including checking DQ5 for an error status) is tricky to get working | 638 | * (including checking DQ5 for an error status) is tricky to get working |
602 | * correctly and is therefore not done (particulary with interleaved chips | 639 | * correctly and is therefore not done (particularly with interleaved chips |
603 | * as each chip must be checked independantly of the others). | 640 | * as each chip must be checked independently of the others). |
604 | * | 641 | * |
605 | */ | 642 | */ |
606 | static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) | 643 | static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected) |
@@ -674,9 +711,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
674 | * there was an error (so leave the erase | 711 | * there was an error (so leave the erase |
675 | * routine to recover from it) or we trying to | 712 | * routine to recover from it) or we trying to |
676 | * use the erase-in-progress sector. */ | 713 | * use the erase-in-progress sector. */ |
677 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | 714 | put_chip(map, chip, adr); |
678 | chip->state = FL_ERASING; | ||
679 | chip->oldstate = FL_READY; | ||
680 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); | 715 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); |
681 | return -EIO; | 716 | return -EIO; |
682 | } | 717 | } |
@@ -726,8 +761,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
726 | 761 | ||
727 | switch(chip->oldstate) { | 762 | switch(chip->oldstate) { |
728 | case FL_ERASING: | 763 | case FL_ERASING: |
729 | chip->state = chip->oldstate; | 764 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
730 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | ||
731 | chip->oldstate = FL_READY; | 765 | chip->oldstate = FL_READY; |
732 | chip->state = FL_ERASING; | 766 | chip->state = FL_ERASING; |
733 | break; | 767 | break; |
@@ -870,7 +904,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, | |||
870 | local_irq_disable(); | 904 | local_irq_disable(); |
871 | 905 | ||
872 | /* Resume the write or erase operation */ | 906 | /* Resume the write or erase operation */ |
873 | map_write(map, CMD(0x30), adr); | 907 | map_write(map, cfi->sector_erase_cmd, adr); |
874 | chip->state = oldstate; | 908 | chip->state = oldstate; |
875 | start = xip_currtime(); | 909 | start = xip_currtime(); |
876 | } else if (usec >= 1000000/HZ) { | 910 | } else if (usec >= 1000000/HZ) { |
@@ -1025,9 +1059,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1025 | mutex_lock(&chip->mutex); | 1059 | mutex_lock(&chip->mutex); |
1026 | 1060 | ||
1027 | if (chip->state != FL_READY){ | 1061 | if (chip->state != FL_READY){ |
1028 | #if 0 | ||
1029 | printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); | ||
1030 | #endif | ||
1031 | set_current_state(TASK_UNINTERRUPTIBLE); | 1062 | set_current_state(TASK_UNINTERRUPTIBLE); |
1032 | add_wait_queue(&chip->wq, &wait); | 1063 | add_wait_queue(&chip->wq, &wait); |
1033 | 1064 | ||
@@ -1035,10 +1066,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1035 | 1066 | ||
1036 | schedule(); | 1067 | schedule(); |
1037 | remove_wait_queue(&chip->wq, &wait); | 1068 | remove_wait_queue(&chip->wq, &wait); |
1038 | #if 0 | ||
1039 | if(signal_pending(current)) | ||
1040 | return -EINTR; | ||
1041 | #endif | ||
1042 | timeo = jiffies + HZ; | 1069 | timeo = jiffies + HZ; |
1043 | 1070 | ||
1044 | goto retry; | 1071 | goto retry; |
@@ -1246,9 +1273,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1246 | mutex_lock(&cfi->chips[chipnum].mutex); | 1273 | mutex_lock(&cfi->chips[chipnum].mutex); |
1247 | 1274 | ||
1248 | if (cfi->chips[chipnum].state != FL_READY) { | 1275 | if (cfi->chips[chipnum].state != FL_READY) { |
1249 | #if 0 | ||
1250 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1251 | #endif | ||
1252 | set_current_state(TASK_UNINTERRUPTIBLE); | 1276 | set_current_state(TASK_UNINTERRUPTIBLE); |
1253 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1277 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1254 | 1278 | ||
@@ -1256,10 +1280,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1256 | 1280 | ||
1257 | schedule(); | 1281 | schedule(); |
1258 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1282 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1259 | #if 0 | ||
1260 | if(signal_pending(current)) | ||
1261 | return -EINTR; | ||
1262 | #endif | ||
1263 | goto retry; | 1283 | goto retry; |
1264 | } | 1284 | } |
1265 | 1285 | ||
@@ -1324,9 +1344,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1324 | mutex_lock(&cfi->chips[chipnum].mutex); | 1344 | mutex_lock(&cfi->chips[chipnum].mutex); |
1325 | 1345 | ||
1326 | if (cfi->chips[chipnum].state != FL_READY) { | 1346 | if (cfi->chips[chipnum].state != FL_READY) { |
1327 | #if 0 | ||
1328 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1329 | #endif | ||
1330 | set_current_state(TASK_UNINTERRUPTIBLE); | 1347 | set_current_state(TASK_UNINTERRUPTIBLE); |
1331 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1348 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1332 | 1349 | ||
@@ -1334,10 +1351,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1334 | 1351 | ||
1335 | schedule(); | 1352 | schedule(); |
1336 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1353 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1337 | #if 0 | ||
1338 | if(signal_pending(current)) | ||
1339 | return -EINTR; | ||
1340 | #endif | ||
1341 | goto retry1; | 1354 | goto retry1; |
1342 | } | 1355 | } |
1343 | 1356 | ||
@@ -1396,7 +1409,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1396 | 1409 | ||
1397 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1410 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1398 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1411 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1399 | //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1400 | 1412 | ||
1401 | /* Write Buffer Load */ | 1413 | /* Write Buffer Load */ |
1402 | map_write(map, CMD(0x25), cmd_adr); | 1414 | map_write(map, CMD(0x25), cmd_adr); |
@@ -1675,7 +1687,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1675 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1687 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1676 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1688 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1677 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1689 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1678 | map_write(map, CMD(0x30), adr); | 1690 | map_write(map, cfi->sector_erase_cmd, adr); |
1679 | 1691 | ||
1680 | chip->state = FL_ERASING; | 1692 | chip->state = FL_ERASING; |
1681 | chip->erase_suspended = 0; | 1693 | chip->erase_suspended = 0; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 314af1f5a370..179814a95f3a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
@@ -238,6 +238,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) | |||
238 | mtd->resume = cfi_staa_resume; | 238 | mtd->resume = cfi_staa_resume; |
239 | mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; | 239 | mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; |
240 | mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ | 240 | mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ |
241 | mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | ||
241 | map->fldrv = &cfi_staa_chipdrv; | 242 | map->fldrv = &cfi_staa_chipdrv; |
242 | __module_get(THIS_MODULE); | 243 | __module_get(THIS_MODULE); |
243 | mtd->name = map->name; | 244 | mtd->name = map->name; |
@@ -295,6 +296,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof | |||
295 | /* make sure we're in 'read status' mode */ | 296 | /* make sure we're in 'read status' mode */ |
296 | map_write(map, CMD(0x70), cmd_addr); | 297 | map_write(map, CMD(0x70), cmd_addr); |
297 | chip->state = FL_ERASING; | 298 | chip->state = FL_ERASING; |
299 | wake_up(&chip->wq); | ||
298 | mutex_unlock(&chip->mutex); | 300 | mutex_unlock(&chip->mutex); |
299 | printk(KERN_ERR "Chip not ready after erase " | 301 | printk(KERN_ERR "Chip not ready after erase " |
300 | "suspended: status = 0x%lx\n", status.x[0]); | 302 | "suspended: status = 0x%lx\n", status.x[0]); |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 8f5b96aa87a0..d25535279404 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
177 | 177 | ||
178 | cfi->cfi_mode = CFI_MODE_CFI; | 178 | cfi->cfi_mode = CFI_MODE_CFI; |
179 | 179 | ||
180 | cfi->sector_erase_cmd = CMD(0x30); | ||
181 | |||
180 | /* Read the CFI info structure */ | 182 | /* Read the CFI info structure */ |
181 | xip_disable_qry(base, map, cfi); | 183 | xip_disable_qry(base, map, cfi); |
182 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) | 184 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index e503b2ca894d..8e464054a631 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Common Flash Interface support: | 2 | * Common Flash Interface support: |
3 | * Generic utility functions not dependant on command set | 3 | * Generic utility functions not dependent on command set |
4 | * | 4 | * |
5 | * Copyright (C) 2002 Red Hat | 5 | * Copyright (C) 2002 Red Hat |
6 | * Copyright (C) 2003 STMicroelectronics Limited | 6 | * Copyright (C) 2003 STMicroelectronics Limited |
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map, | |||
77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); | 77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); |
78 | if (cfi_qry_present(map, base, cfi)) | 78 | if (cfi_qry_present(map, base, cfi)) |
79 | return 1; | 79 | return 1; |
80 | /* SST 39VF640xB */ | ||
81 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
82 | cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
83 | cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL); | ||
84 | cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
85 | if (cfi_qry_present(map, base, cfi)) | ||
86 | return 1; | ||
80 | /* QRY not found */ | 87 | /* QRY not found */ |
81 | return 0; | 88 | return 0; |
82 | } | 89 | } |
@@ -149,7 +156,7 @@ void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups) | |||
149 | for (f=fixups; f->fixup; f++) { | 156 | for (f=fixups; f->fixup; f++) { |
150 | if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && | 157 | if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && |
151 | ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { | 158 | ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { |
152 | f->fixup(mtd, f->param); | 159 | f->fixup(mtd); |
153 | } | 160 | } |
154 | } | 161 | } |
155 | } | 162 | } |
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h index d18064977192..5e3cc80128aa 100644 --- a/drivers/mtd/chips/fwh_lock.h +++ b/drivers/mtd/chips/fwh_lock.h | |||
@@ -98,7 +98,7 @@ static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
98 | return ret; | 98 | return ret; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param) | 101 | static void fixup_use_fwh_lock(struct mtd_info *mtd) |
102 | { | 102 | { |
103 | printk(KERN_NOTICE "using fwh lock/unlock method\n"); | 103 | printk(KERN_NOTICE "using fwh lock/unlock method\n"); |
104 | /* Setup for the chips with the fwh lock method */ | 104 | /* Setup for the chips with the fwh lock method */ |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index d72a5fb2d041..ea832ea0e4aa 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -1935,14 +1935,14 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) | |||
1935 | } | 1935 | } |
1936 | 1936 | ||
1937 | 1937 | ||
1938 | static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | 1938 | static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int index) |
1939 | { | 1939 | { |
1940 | int i,num_erase_regions; | 1940 | int i,num_erase_regions; |
1941 | uint8_t uaddr; | 1941 | uint8_t uaddr; |
1942 | 1942 | ||
1943 | if (! (jedec_table[index].devtypes & p_cfi->device_type)) { | 1943 | if (!(jedec_table[index].devtypes & cfi->device_type)) { |
1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", | 1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", |
1945 | jedec_table[index].name, 4 * (1<<p_cfi->device_type)); | 1945 | jedec_table[index].name, 4 * (1<<cfi->device_type)); |
1946 | return 0; | 1946 | return 0; |
1947 | } | 1947 | } |
1948 | 1948 | ||
@@ -1950,27 +1950,28 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | |||
1950 | 1950 | ||
1951 | num_erase_regions = jedec_table[index].nr_regions; | 1951 | num_erase_regions = jedec_table[index].nr_regions; |
1952 | 1952 | ||
1953 | p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); | 1953 | cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); |
1954 | if (!p_cfi->cfiq) { | 1954 | if (!cfi->cfiq) { |
1955 | //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); | 1955 | //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); |
1956 | return 0; | 1956 | return 0; |
1957 | } | 1957 | } |
1958 | 1958 | ||
1959 | memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); | 1959 | memset(cfi->cfiq, 0, sizeof(struct cfi_ident)); |
1960 | 1960 | ||
1961 | p_cfi->cfiq->P_ID = jedec_table[index].cmd_set; | 1961 | cfi->cfiq->P_ID = jedec_table[index].cmd_set; |
1962 | p_cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; | 1962 | cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; |
1963 | p_cfi->cfiq->DevSize = jedec_table[index].dev_size; | 1963 | cfi->cfiq->DevSize = jedec_table[index].dev_size; |
1964 | p_cfi->cfi_mode = CFI_MODE_JEDEC; | 1964 | cfi->cfi_mode = CFI_MODE_JEDEC; |
1965 | cfi->sector_erase_cmd = CMD(0x30); | ||
1965 | 1966 | ||
1966 | for (i=0; i<num_erase_regions; i++){ | 1967 | for (i=0; i<num_erase_regions; i++){ |
1967 | p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; | 1968 | cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; |
1968 | } | 1969 | } |
1969 | p_cfi->cmdset_priv = NULL; | 1970 | cfi->cmdset_priv = NULL; |
1970 | 1971 | ||
1971 | /* This may be redundant for some cases, but it doesn't hurt */ | 1972 | /* This may be redundant for some cases, but it doesn't hurt */ |
1972 | p_cfi->mfr = jedec_table[index].mfr_id; | 1973 | cfi->mfr = jedec_table[index].mfr_id; |
1973 | p_cfi->id = jedec_table[index].dev_id; | 1974 | cfi->id = jedec_table[index].dev_id; |
1974 | 1975 | ||
1975 | uaddr = jedec_table[index].uaddr; | 1976 | uaddr = jedec_table[index].uaddr; |
1976 | 1977 | ||
@@ -1978,8 +1979,8 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | |||
1978 | our brains explode when we see the datasheets talking about address | 1979 | our brains explode when we see the datasheets talking about address |
1979 | lines numbered from A-1 to A18. The CFI table has unlock addresses | 1980 | lines numbered from A-1 to A18. The CFI table has unlock addresses |
1980 | in device-words according to the mode the device is connected in */ | 1981 | in device-words according to the mode the device is connected in */ |
1981 | p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / p_cfi->device_type; | 1982 | cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / cfi->device_type; |
1982 | p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / p_cfi->device_type; | 1983 | cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / cfi->device_type; |
1983 | 1984 | ||
1984 | return 1; /* ok */ | 1985 | return 1; /* ok */ |
1985 | } | 1986 | } |
@@ -2074,7 +2075,7 @@ static inline int jedec_match( uint32_t base, | |||
2074 | } | 2075 | } |
2075 | 2076 | ||
2076 | /* | 2077 | /* |
2077 | * Make sure the ID's dissappear when the device is taken out of | 2078 | * Make sure the ID's disappear when the device is taken out of |
2078 | * ID mode. The only time this should fail when it should succeed | 2079 | * ID mode. The only time this should fail when it should succeed |
2079 | * is when the ID's are written as data to the same | 2080 | * is when the ID's are written as data to the same |
2080 | * addresses. For this rare and unfortunate case the chip | 2081 | * addresses. For this rare and unfortunate case the chip |
@@ -2175,7 +2176,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
2175 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | 2176 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", |
2176 | __func__, cfi->mfr, cfi->id, | 2177 | __func__, cfi->mfr, cfi->id, |
2177 | cfi->addr_unlock1, cfi->addr_unlock2 ); | 2178 | cfi->addr_unlock1, cfi->addr_unlock2 ); |
2178 | if (!cfi_jedec_setup(cfi, i)) | 2179 | if (!cfi_jedec_setup(map, cfi, i)) |
2179 | return 0; | 2180 | return 0; |
2180 | goto ok_out; | 2181 | goto ok_out; |
2181 | } | 2182 | } |