aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c88
-rw-r--r--drivers/mtd/chips/gen_probe.c3
-rw-r--r--include/linux/mtd/cfi.h13
-rw-r--r--include/linux/mtd/mtd.h14
-rw-r--r--include/mtd/mtd-abi.h3
5 files changed, 92 insertions, 29 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
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index e6b6a1c66bd5..360cf626c288 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -1,7 +1,7 @@
1 1
2/* Common Flash Interface structures 2/* Common Flash Interface structures
3 * See http://support.intel.com/design/flash/technote/index.htm 3 * See http://support.intel.com/design/flash/technote/index.htm
4 * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $ 4 * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $
5 */ 5 */
6 6
7#ifndef __MTD_CFI_H__ 7#ifndef __MTD_CFI_H__
@@ -173,6 +173,15 @@ struct cfi_intelext_regioninfo {
173 struct cfi_intelext_blockinfo BlockTypes[1]; 173 struct cfi_intelext_blockinfo BlockTypes[1];
174} __attribute__((packed)); 174} __attribute__((packed));
175 175
176struct cfi_intelext_programming_regioninfo {
177 uint8_t ProgRegShift;
178 uint8_t Reserved1;
179 uint8_t ControlValid;
180 uint8_t Reserved2;
181 uint8_t ControlInvalid;
182 uint8_t Reserved3;
183} __attribute__((packed));
184
176/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ 185/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */
177 186
178struct cfi_pri_amdstd { 187struct cfi_pri_amdstd {
@@ -316,7 +325,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
316#define CMD(x) cfi_build_cmd((x), map, cfi) 325#define CMD(x) cfi_build_cmd((x), map, cfi)
317 326
318 327
319static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, 328static inline unsigned long cfi_merge_status(map_word val, struct map_info *map,
320 struct cfi_private *cfi) 329 struct cfi_private *cfi)
321{ 330{
322 int wordwidth, words_per_bus, chip_mode, chips_per_word; 331 int wordwidth, words_per_bus, chip_mode, chips_per_word;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index c50c3f3927d9..ab5804183916 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $ 2 * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $
3 * 3 *
4 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. 4 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
5 * 5 *
@@ -72,7 +72,17 @@ struct mtd_info {
72 u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) 72 u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
73 u_int32_t ecctype; 73 u_int32_t ecctype;
74 u_int32_t eccsize; 74 u_int32_t eccsize;
75 75
76 /*
77 * Reuse some of the above unused fields in the case of NOR flash
78 * with configurable programming regions to avoid modifying the
79 * user visible structure layout/size. Only valid when the
80 * MTD_PROGRAM_REGIONS flag is set.
81 * (Maybe we should have an union for those?)
82 */
83#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock
84#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize
85#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype
76 86
77 // Kernel-only stuff starts here. 87 // Kernel-only stuff starts here.
78 char *name; 88 char *name;
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 428d9122940b..16e74cafd0b4 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $ 2 * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $
3 * 3 *
4 * Portions of MTD ABI definition which are shared by kernel and user space 4 * Portions of MTD ABI definition which are shared by kernel and user space
5 */ 5 */
@@ -42,6 +42,7 @@ struct mtd_oob_buf {
42#define MTD_OOB 64 // Out-of-band data (NAND flash) 42#define MTD_OOB 64 // Out-of-band data (NAND flash)
43#define MTD_ECC 128 // Device capable of automatic ECC 43#define MTD_ECC 128 // Device capable of automatic ECC
44#define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed 44#define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed
45#define MTD_PROGRAM_REGIONS 512 // Configurable Programming Regions
45 46
46// Some common devices / combinations of capabilities 47// Some common devices / combinations of capabilities
47#define MTD_CAP_ROM 0 48#define MTD_CAP_ROM 0