diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 88 | ||||
-rw-r--r-- | drivers/mtd/chips/gen_probe.c | 3 |
2 files changed, 67 insertions, 24 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 308855e80f66..10c50604bcd5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * (C) 2000 Red Hat. GPL'd | 5 | * (C) 2000 Red Hat. GPL'd |
6 | * | 6 | * |
7 | * $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $ | 7 | * $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $ |
8 | * | 8 | * |
9 | * | 9 | * |
10 | * 10/10/2000 Nicolas Pitre <nico@cam.org> | 10 | * 10/10/2000 Nicolas Pitre <nico@cam.org> |
@@ -105,6 +105,7 @@ static struct mtd_chip_driver cfi_intelext_chipdrv = { | |||
105 | static void cfi_tell_features(struct cfi_pri_intelext *extp) | 105 | static void cfi_tell_features(struct cfi_pri_intelext *extp) |
106 | { | 106 | { |
107 | int i; | 107 | int i; |
108 | printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion); | ||
108 | printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); | 109 | printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); |
109 | printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); | 110 | printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); |
110 | printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); | 111 | printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); |
@@ -116,7 +117,8 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) | |||
116 | printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); | 117 | printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); |
117 | printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); | 118 | printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); |
118 | printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); | 119 | printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); |
119 | for (i=10; i<32; i++) { | 120 | printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported"); |
121 | for (i=11; i<32; i++) { | ||
120 | if (extp->FeatureSupport & (1<<i)) | 122 | if (extp->FeatureSupport & (1<<i)) |
121 | printk(" - Unknown Bit %X: supported\n", i); | 123 | printk(" - Unknown Bit %X: supported\n", i); |
122 | } | 124 | } |
@@ -130,12 +132,18 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) | |||
130 | 132 | ||
131 | printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask); | 133 | printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask); |
132 | printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); | 134 | printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); |
133 | printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); | 135 | printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); |
134 | for (i=2; i<16; i++) { | 136 | for (i=2; i<3; i++) { |
135 | if (extp->BlkStatusRegMask & (1<<i)) | 137 | if (extp->BlkStatusRegMask & (1<<i)) |
136 | printk(" - Unknown Bit %X Active: yes\n",i); | 138 | printk(" - Unknown Bit %X Active: yes\n",i); |
137 | } | 139 | } |
138 | 140 | printk(" - EFA Lock Bit: %s\n", extp->BlkStatusRegMask&16?"yes":"no"); | |
141 | printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no"); | ||
142 | for (i=6; i<16; i++) { | ||
143 | if (extp->BlkStatusRegMask & (1<<i)) | ||
144 | printk(" - Unknown Bit %X Active: yes\n",i); | ||
145 | } | ||
146 | |||
139 | printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", | 147 | printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", |
140 | extp->VccOptimal >> 4, extp->VccOptimal & 0xf); | 148 | extp->VccOptimal >> 4, extp->VccOptimal & 0xf); |
141 | if (extp->VppOptimal) | 149 | if (extp->VppOptimal) |
@@ -253,7 +261,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
253 | return NULL; | 261 | return NULL; |
254 | 262 | ||
255 | if (extp->MajorVersion != '1' || | 263 | if (extp->MajorVersion != '1' || |
256 | (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { | 264 | (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { |
257 | printk(KERN_ERR " Unknown Intel/Sharp Extended Query " | 265 | printk(KERN_ERR " Unknown Intel/Sharp Extended Query " |
258 | "version %c.%c.\n", extp->MajorVersion, | 266 | "version %c.%c.\n", extp->MajorVersion, |
259 | extp->MinorVersion); | 267 | extp->MinorVersion); |
@@ -266,7 +274,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
266 | extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); | 274 | extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); |
267 | extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); | 275 | extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); |
268 | 276 | ||
269 | if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { | 277 | if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') { |
270 | unsigned int extra_size = 0; | 278 | unsigned int extra_size = 0; |
271 | int nb_parts, i; | 279 | int nb_parts, i; |
272 | 280 | ||
@@ -275,7 +283,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
275 | sizeof(struct cfi_intelext_otpinfo); | 283 | sizeof(struct cfi_intelext_otpinfo); |
276 | 284 | ||
277 | /* Burst Read info */ | 285 | /* Burst Read info */ |
278 | extra_size += 6; | 286 | extra_size += (extp->MinorVersion < '4') ? 6 : 5; |
279 | 287 | ||
280 | /* Number of hardware-partitions */ | 288 | /* Number of hardware-partitions */ |
281 | extra_size += 1; | 289 | extra_size += 1; |
@@ -283,6 +291,10 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
283 | goto need_more; | 291 | goto need_more; |
284 | nb_parts = extp->extra[extra_size - 1]; | 292 | nb_parts = extp->extra[extra_size - 1]; |
285 | 293 | ||
294 | /* skip the sizeof(partregion) field in CFI 1.4 */ | ||
295 | if (extp->MinorVersion >= '4') | ||
296 | extra_size += 2; | ||
297 | |||
286 | for (i = 0; i < nb_parts; i++) { | 298 | for (i = 0; i < nb_parts; i++) { |
287 | struct cfi_intelext_regioninfo *rinfo; | 299 | struct cfi_intelext_regioninfo *rinfo; |
288 | rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; | 300 | rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; |
@@ -294,6 +306,9 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
294 | * sizeof(struct cfi_intelext_blockinfo); | 306 | * sizeof(struct cfi_intelext_blockinfo); |
295 | } | 307 | } |
296 | 308 | ||
309 | if (extp->MinorVersion >= '4') | ||
310 | extra_size += sizeof(struct cfi_intelext_programming_regioninfo); | ||
311 | |||
297 | if (extp_size < sizeof(*extp) + extra_size) { | 312 | if (extp_size < sizeof(*extp) + extra_size) { |
298 | need_more: | 313 | need_more: |
299 | extp_size = sizeof(*extp) + extra_size; | 314 | extp_size = sizeof(*extp) + extra_size; |
@@ -490,7 +505,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
490 | * arrangement at this point. This can be rearranged in the future | 505 | * arrangement at this point. This can be rearranged in the future |
491 | * if someone feels motivated enough. --nico | 506 | * if someone feels motivated enough. --nico |
492 | */ | 507 | */ |
493 | if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' | 508 | if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' |
494 | && extp->FeatureSupport & (1 << 9)) { | 509 | && extp->FeatureSupport & (1 << 9)) { |
495 | struct cfi_private *newcfi; | 510 | struct cfi_private *newcfi; |
496 | struct flchip *chip; | 511 | struct flchip *chip; |
@@ -502,12 +517,16 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
502 | sizeof(struct cfi_intelext_otpinfo); | 517 | sizeof(struct cfi_intelext_otpinfo); |
503 | 518 | ||
504 | /* Burst Read info */ | 519 | /* Burst Read info */ |
505 | offs += 6; | 520 | offs += (extp->MinorVersion < '4') ? 6 : 5; |
506 | 521 | ||
507 | /* Number of partition regions */ | 522 | /* Number of partition regions */ |
508 | numregions = extp->extra[offs]; | 523 | numregions = extp->extra[offs]; |
509 | offs += 1; | 524 | offs += 1; |
510 | 525 | ||
526 | /* skip the sizeof(partregion) field in CFI 1.4 */ | ||
527 | if (extp->MinorVersion >= '4') | ||
528 | offs += 2; | ||
529 | |||
511 | /* Number of hardware partitions */ | 530 | /* Number of hardware partitions */ |
512 | numparts = 0; | 531 | numparts = 0; |
513 | for (i = 0; i < numregions; i++) { | 532 | for (i = 0; i < numregions; i++) { |
@@ -519,6 +538,20 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
519 | sizeof(struct cfi_intelext_blockinfo); | 538 | sizeof(struct cfi_intelext_blockinfo); |
520 | } | 539 | } |
521 | 540 | ||
541 | /* Programming Region info */ | ||
542 | if (extp->MinorVersion >= '4') { | ||
543 | struct cfi_intelext_programming_regioninfo *prinfo; | ||
544 | prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs]; | ||
545 | MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift; | ||
546 | MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid; | ||
547 | MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid; | ||
548 | mtd->flags |= MTD_PROGRAM_REGIONS; | ||
549 | printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n", | ||
550 | map->name, MTD_PROGREGION_SIZE(mtd), | ||
551 | MTD_PROGREGION_CTRLMODE_VALID(mtd), | ||
552 | MTD_PROGREGION_CTRLMODE_INVALID(mtd)); | ||
553 | } | ||
554 | |||
522 | /* | 555 | /* |
523 | * All functions below currently rely on all chips having | 556 | * All functions below currently rely on all chips having |
524 | * the same geometry so we'll just assume that all hardware | 557 | * the same geometry so we'll just assume that all hardware |
@@ -1222,12 +1255,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1222 | 1255 | ||
1223 | adr += chip->start; | 1256 | adr += chip->start; |
1224 | 1257 | ||
1225 | /* Let's determine this according to the interleave only once */ | 1258 | /* Let's determine those according to the interleave only once */ |
1226 | status_OK = CMD(0x80); | 1259 | status_OK = CMD(0x80); |
1227 | switch (mode) { | 1260 | switch (mode) { |
1228 | case FL_WRITING: write_cmd = CMD(0x40); break; | 1261 | case FL_WRITING: |
1229 | case FL_OTP_WRITE: write_cmd = CMD(0xc0); break; | 1262 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); |
1230 | default: return -EINVAL; | 1263 | break; |
1264 | case FL_OTP_WRITE: | ||
1265 | write_cmd = CMD(0xc0); | ||
1266 | break; | ||
1267 | default: | ||
1268 | return -EINVAL; | ||
1231 | } | 1269 | } |
1232 | 1270 | ||
1233 | spin_lock(chip->mutex); | 1271 | spin_lock(chip->mutex); |
@@ -1410,16 +1448,17 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1410 | unsigned long adr, const u_char *buf, int len) | 1448 | unsigned long adr, const u_char *buf, int len) |
1411 | { | 1449 | { |
1412 | struct cfi_private *cfi = map->fldrv_priv; | 1450 | struct cfi_private *cfi = map->fldrv_priv; |
1413 | map_word status, status_OK; | 1451 | map_word status, status_OK, write_cmd; |
1414 | unsigned long cmd_adr, timeo; | 1452 | unsigned long cmd_adr, timeo; |
1415 | int wbufsize, z, ret=0, bytes, words; | 1453 | int wbufsize, z, ret=0, bytes, words; |
1416 | 1454 | ||
1417 | wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | 1455 | wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; |
1418 | adr += chip->start; | 1456 | adr += chip->start; |
1419 | cmd_adr = adr & ~(wbufsize-1); | 1457 | cmd_adr = adr & ~(wbufsize-1); |
1420 | 1458 | ||
1421 | /* Let's determine this according to the interleave only once */ | 1459 | /* Let's determine this according to the interleave only once */ |
1422 | status_OK = CMD(0x80); | 1460 | status_OK = CMD(0x80); |
1461 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); | ||
1423 | 1462 | ||
1424 | spin_lock(chip->mutex); | 1463 | spin_lock(chip->mutex); |
1425 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); | 1464 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); |
@@ -1451,7 +1490,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1451 | 1490 | ||
1452 | z = 0; | 1491 | z = 0; |
1453 | for (;;) { | 1492 | for (;;) { |
1454 | map_write(map, CMD(0xe8), cmd_adr); | 1493 | map_write(map, write_cmd, cmd_adr); |
1455 | 1494 | ||
1456 | status = map_read(map, cmd_adr); | 1495 | status = map_read(map, cmd_adr); |
1457 | if (map_word_andequal(map, status, status_OK, status_OK)) | 1496 | if (map_word_andequal(map, status, status_OK, status_OK)) |
@@ -2380,20 +2419,23 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) | |||
2380 | kfree(mtd->eraseregions); | 2419 | kfree(mtd->eraseregions); |
2381 | } | 2420 | } |
2382 | 2421 | ||
2383 | static char im_name_1[]="cfi_cmdset_0001"; | 2422 | static char im_name_0001[] = "cfi_cmdset_0001"; |
2384 | static char im_name_3[]="cfi_cmdset_0003"; | 2423 | static char im_name_0003[] = "cfi_cmdset_0003"; |
2424 | static char im_name_0200[] = "cfi_cmdset_0200"; | ||
2385 | 2425 | ||
2386 | static int __init cfi_intelext_init(void) | 2426 | static int __init cfi_intelext_init(void) |
2387 | { | 2427 | { |
2388 | inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); | 2428 | inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001); |
2389 | inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); | 2429 | inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001); |
2430 | inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); | ||
2390 | return 0; | 2431 | return 0; |
2391 | } | 2432 | } |
2392 | 2433 | ||
2393 | static void __exit cfi_intelext_exit(void) | 2434 | static void __exit cfi_intelext_exit(void) |
2394 | { | 2435 | { |
2395 | inter_module_unregister(im_name_1); | 2436 | inter_module_unregister(im_name_0001); |
2396 | inter_module_unregister(im_name_3); | 2437 | inter_module_unregister(im_name_0003); |
2438 | inter_module_unregister(im_name_0200); | ||
2397 | } | 2439 | } |
2398 | 2440 | ||
2399 | module_init(cfi_intelext_init); | 2441 | module_init(cfi_intelext_init); |
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index dc065b22f79e..28807eb9fc86 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Routines common to all CFI-type probes. | 2 | * Routines common to all CFI-type probes. |
3 | * (C) 2001-2003 Red Hat, Inc. | 3 | * (C) 2001-2003 Red Hat, Inc. |
4 | * GPL'd | 4 | * GPL'd |
5 | * $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $ | 5 | * $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
@@ -235,6 +235,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) | |||
235 | #ifdef CONFIG_MTD_CFI_INTELEXT | 235 | #ifdef CONFIG_MTD_CFI_INTELEXT |
236 | case 0x0001: | 236 | case 0x0001: |
237 | case 0x0003: | 237 | case 0x0003: |
238 | case 0x0200: | ||
238 | return cfi_cmdset_0001(map, primary); | 239 | return cfi_cmdset_0001(map, primary); |
239 | #endif | 240 | #endif |
240 | #ifdef CONFIG_MTD_CFI_AMDSTD | 241 | #ifdef CONFIG_MTD_CFI_AMDSTD |