aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/chips
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2005-08-06 00:40:46 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 14:12:17 -0500
commit638d983840bb64e02c29bdd6160bb9963f4090f7 (patch)
treef07e85847009236731f8cb2b9afcba35d40849b1 /drivers/mtd/chips
parent4843653cab0db036399f77d9355db31ce39cb8b9 (diff)
{MTD] add support for Intel's "Sibley" flash
This updates the Primary Vendor-Specific Extended Query parsing to version 1.4 in order to get the information about the Configurable Programming Mode regions implemented in the Sibley flash, as well as selecting the appropriate write command code. This flash does not behave like traditional NOR flash when writing data. While mtdblock should just work, further changes are needed for JFFS2 use. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c88
-rw-r--r--drivers/mtd/chips/gen_probe.c3
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 = {
105static void cfi_tell_features(struct cfi_pri_intelext *extp) 105static 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
2383static char im_name_1[]="cfi_cmdset_0001"; 2422static char im_name_0001[] = "cfi_cmdset_0001";
2384static char im_name_3[]="cfi_cmdset_0003"; 2423static char im_name_0003[] = "cfi_cmdset_0003";
2424static char im_name_0200[] = "cfi_cmdset_0200";
2385 2425
2386static int __init cfi_intelext_init(void) 2426static 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
2393static void __exit cfi_intelext_exit(void) 2434static 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
2399module_init(cfi_intelext_init); 2441module_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