aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/diskonchip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/diskonchip.c')
-rw-r--r--drivers/mtd/nand/diskonchip.c96
1 files changed, 54 insertions, 42 deletions
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 02135c3ac29a..fdb5d4ad3d52 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -16,7 +16,7 @@
16 * 16 *
17 * Interface to generic NAND code for M-Systems DiskOnChip devices 17 * Interface to generic NAND code for M-Systems DiskOnChip devices
18 * 18 *
19 * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $ 19 * $Id: diskonchip.c,v 1.54 2005/04/07 14:22:55 dbrown Exp $
20 */ 20 */
21 21
22#include <linux/kernel.h> 22#include <linux/kernel.h>
@@ -35,13 +35,13 @@
35#include <linux/mtd/inftl.h> 35#include <linux/mtd/inftl.h>
36 36
37/* Where to look for the devices? */ 37/* Where to look for the devices? */
38#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 38#ifndef CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS
39#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0 39#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0
40#endif 40#endif
41 41
42static unsigned long __initdata doc_locations[] = { 42static unsigned long __initdata doc_locations[] = {
43#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) 43#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
44#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH 44#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH
45 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 45 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
46 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, 46 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
47 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, 47 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
@@ -81,11 +81,6 @@ struct doc_priv {
81 struct mtd_info *nextdoc; 81 struct mtd_info *nextdoc;
82}; 82};
83 83
84/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL
85 MediaHeader. The spec says to just keep going, I think, but that's just
86 silly. */
87#define MAX_MEDIAHEADER_SCAN 8
88
89/* This is the syndrome computed by the HW ecc generator upon reading an empty 84/* This is the syndrome computed by the HW ecc generator upon reading an empty
90 page, one with all 0xff for data and stored ecc code. */ 85 page, one with all 0xff for data and stored ecc code. */
91static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; 86static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
@@ -111,10 +106,11 @@ module_param(try_dword, int, 0);
111static int no_ecc_failures=0; 106static int no_ecc_failures=0;
112module_param(no_ecc_failures, int, 0); 107module_param(no_ecc_failures, int, 0);
113 108
114#ifdef CONFIG_MTD_PARTITIONS
115static int no_autopart=0; 109static int no_autopart=0;
116module_param(no_autopart, int, 0); 110module_param(no_autopart, int, 0);
117#endif 111
112static int show_firmware_partition=0;
113module_param(show_firmware_partition, int, 0);
118 114
119#ifdef MTD_NAND_DISKONCHIP_BBTWRITE 115#ifdef MTD_NAND_DISKONCHIP_BBTWRITE
120static int inftl_bbt_write=1; 116static int inftl_bbt_write=1;
@@ -123,7 +119,7 @@ static int inftl_bbt_write=0;
123#endif 119#endif
124module_param(inftl_bbt_write, int, 0); 120module_param(inftl_bbt_write, int, 0);
125 121
126static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; 122static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS;
127module_param(doc_config_location, ulong, 0); 123module_param(doc_config_location, ulong, 0);
128MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); 124MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
129 125
@@ -410,7 +406,12 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
410 doc200x_hwcontrol(mtd, NAND_CTL_SETALE); 406 doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
411 this->write_byte(mtd, 0); 407 this->write_byte(mtd, 0);
412 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); 408 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
413 409
410 /* We cant' use dev_ready here, but at least we wait for the
411 * command to complete
412 */
413 udelay(50);
414
414 ret = this->read_byte(mtd) << 8; 415 ret = this->read_byte(mtd) << 8;
415 ret |= this->read_byte(mtd); 416 ret |= this->read_byte(mtd);
416 417
@@ -429,6 +430,8 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
429 doc2000_write_byte(mtd, 0); 430 doc2000_write_byte(mtd, 0);
430 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); 431 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
431 432
433 udelay(50);
434
432 ident.dword = readl(docptr + DoC_2k_CDSN_IO); 435 ident.dword = readl(docptr + DoC_2k_CDSN_IO);
433 if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { 436 if (((ident.byte[0] << 8) | ident.byte[1]) == ret) {
434 printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n"); 437 printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n");
@@ -1046,11 +1049,21 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
1046 1049
1047//u_char mydatabuf[528]; 1050//u_char mydatabuf[528];
1048 1051
1052/* The strange out-of-order .oobfree list below is a (possibly unneeded)
1053 * attempt to retain compatibility. It used to read:
1054 * .oobfree = { {8, 8} }
1055 * Since that leaves two bytes unusable, it was changed. But the following
1056 * scheme might affect existing jffs2 installs by moving the cleanmarker:
1057 * .oobfree = { {6, 10} }
1058 * jffs2 seems to handle the above gracefully, but the current scheme seems
1059 * safer. The only problem with it is that any code that parses oobfree must
1060 * be able to handle out-of-order segments.
1061 */
1049static struct nand_oobinfo doc200x_oobinfo = { 1062static struct nand_oobinfo doc200x_oobinfo = {
1050 .useecc = MTD_NANDECC_AUTOPLACE, 1063 .useecc = MTD_NANDECC_AUTOPLACE,
1051 .eccbytes = 6, 1064 .eccbytes = 6,
1052 .eccpos = {0, 1, 2, 3, 4, 5}, 1065 .eccpos = {0, 1, 2, 3, 4, 5},
1053 .oobfree = { {8, 8} } 1066 .oobfree = { {8, 8}, {6, 2} }
1054}; 1067};
1055 1068
1056/* Find the (I)NFTL Media Header, and optionally also the mirror media header. 1069/* Find the (I)NFTL Media Header, and optionally also the mirror media header.
@@ -1064,12 +1077,11 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
1064{ 1077{
1065 struct nand_chip *this = mtd->priv; 1078 struct nand_chip *this = mtd->priv;
1066 struct doc_priv *doc = this->priv; 1079 struct doc_priv *doc = this->priv;
1067 unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift); 1080 unsigned offs;
1068 int ret; 1081 int ret;
1069 size_t retlen; 1082 size_t retlen;
1070 1083
1071 end = min(end, mtd->size); // paranoia 1084 for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
1072 for (offs = 0; offs < end; offs += mtd->erasesize) {
1073 ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); 1085 ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
1074 if (retlen != mtd->oobblock) continue; 1086 if (retlen != mtd->oobblock) continue;
1075 if (ret) { 1087 if (ret) {
@@ -1111,6 +1123,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
1111 u_char *buf; 1123 u_char *buf;
1112 struct NFTLMediaHeader *mh; 1124 struct NFTLMediaHeader *mh;
1113 const unsigned psize = 1 << this->page_shift; 1125 const unsigned psize = 1 << this->page_shift;
1126 int numparts = 0;
1114 unsigned blocks, maxblocks; 1127 unsigned blocks, maxblocks;
1115 int offs, numheaders; 1128 int offs, numheaders;
1116 1129
@@ -1122,8 +1135,10 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
1122 if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; 1135 if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
1123 mh = (struct NFTLMediaHeader *) buf; 1136 mh = (struct NFTLMediaHeader *) buf;
1124 1137
1125//#ifdef CONFIG_MTD_DEBUG_VERBOSE 1138 mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
1126// if (CONFIG_MTD_DEBUG_VERBOSE >= 2) 1139 mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
1140 mh->FormattedSize = le32_to_cpu(mh->FormattedSize);
1141
1127 printk(KERN_INFO " DataOrgID = %s\n" 1142 printk(KERN_INFO " DataOrgID = %s\n"
1128 " NumEraseUnits = %d\n" 1143 " NumEraseUnits = %d\n"
1129 " FirstPhysicalEUN = %d\n" 1144 " FirstPhysicalEUN = %d\n"
@@ -1132,7 +1147,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
1132 mh->DataOrgID, mh->NumEraseUnits, 1147 mh->DataOrgID, mh->NumEraseUnits,
1133 mh->FirstPhysicalEUN, mh->FormattedSize, 1148 mh->FirstPhysicalEUN, mh->FormattedSize,
1134 mh->UnitSizeFactor); 1149 mh->UnitSizeFactor);
1135//#endif
1136 1150
1137 blocks = mtd->size >> this->phys_erase_shift; 1151 blocks = mtd->size >> this->phys_erase_shift;
1138 maxblocks = min(32768U, mtd->erasesize - psize); 1152 maxblocks = min(32768U, mtd->erasesize - psize);
@@ -1175,23 +1189,28 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
1175 offs <<= this->page_shift; 1189 offs <<= this->page_shift;
1176 offs += mtd->erasesize; 1190 offs += mtd->erasesize;
1177 1191
1178 //parts[0].name = " DiskOnChip Boot / Media Header partition"; 1192 if (show_firmware_partition == 1) {
1179 //parts[0].offset = 0; 1193 parts[0].name = " DiskOnChip Firmware / Media Header partition";
1180 //parts[0].size = offs; 1194 parts[0].offset = 0;
1195 parts[0].size = offs;
1196 numparts = 1;
1197 }
1181 1198
1182 parts[0].name = " DiskOnChip BDTL partition"; 1199 parts[numparts].name = " DiskOnChip BDTL partition";
1183 parts[0].offset = offs; 1200 parts[numparts].offset = offs;
1184 parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; 1201 parts[numparts].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift;
1202
1203 offs += parts[numparts].size;
1204 numparts++;
1185 1205
1186 offs += parts[0].size;
1187 if (offs < mtd->size) { 1206 if (offs < mtd->size) {
1188 parts[1].name = " DiskOnChip Remainder partition"; 1207 parts[numparts].name = " DiskOnChip Remainder partition";
1189 parts[1].offset = offs; 1208 parts[numparts].offset = offs;
1190 parts[1].size = mtd->size - offs; 1209 parts[numparts].size = mtd->size - offs;
1191 ret = 2; 1210 numparts++;
1192 goto out;
1193 } 1211 }
1194 ret = 1; 1212
1213 ret = numparts;
1195out: 1214out:
1196 kfree(buf); 1215 kfree(buf);
1197 return ret; 1216 return ret;
@@ -1233,8 +1252,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
1233 mh->FormatFlags = le32_to_cpu(mh->FormatFlags); 1252 mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
1234 mh->PercentUsed = le32_to_cpu(mh->PercentUsed); 1253 mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
1235 1254
1236//#ifdef CONFIG_MTD_DEBUG_VERBOSE
1237// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
1238 printk(KERN_INFO " bootRecordID = %s\n" 1255 printk(KERN_INFO " bootRecordID = %s\n"
1239 " NoOfBootImageBlocks = %d\n" 1256 " NoOfBootImageBlocks = %d\n"
1240 " NoOfBinaryPartitions = %d\n" 1257 " NoOfBinaryPartitions = %d\n"
@@ -1252,7 +1269,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
1252 ((unsigned char *) &mh->OsakVersion)[2] & 0xf, 1269 ((unsigned char *) &mh->OsakVersion)[2] & 0xf,
1253 ((unsigned char *) &mh->OsakVersion)[3] & 0xf, 1270 ((unsigned char *) &mh->OsakVersion)[3] & 0xf,
1254 mh->PercentUsed); 1271 mh->PercentUsed);
1255//#endif
1256 1272
1257 vshift = this->phys_erase_shift + mh->BlockMultiplierBits; 1273 vshift = this->phys_erase_shift + mh->BlockMultiplierBits;
1258 1274
@@ -1278,8 +1294,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
1278 ip->spareUnits = le32_to_cpu(ip->spareUnits); 1294 ip->spareUnits = le32_to_cpu(ip->spareUnits);
1279 ip->Reserved0 = le32_to_cpu(ip->Reserved0); 1295 ip->Reserved0 = le32_to_cpu(ip->Reserved0);
1280 1296
1281//#ifdef CONFIG_MTD_DEBUG_VERBOSE
1282// if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
1283 printk(KERN_INFO " PARTITION[%d] ->\n" 1297 printk(KERN_INFO " PARTITION[%d] ->\n"
1284 " virtualUnits = %d\n" 1298 " virtualUnits = %d\n"
1285 " firstUnit = %d\n" 1299 " firstUnit = %d\n"
@@ -1289,16 +1303,14 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
1289 i, ip->virtualUnits, ip->firstUnit, 1303 i, ip->virtualUnits, ip->firstUnit,
1290 ip->lastUnit, ip->flags, 1304 ip->lastUnit, ip->flags,
1291 ip->spareUnits); 1305 ip->spareUnits);
1292//#endif
1293 1306
1294/* 1307 if ((show_firmware_partition == 1) &&
1295 if ((i == 0) && (ip->firstUnit > 0)) { 1308 (i == 0) && (ip->firstUnit > 0)) {
1296 parts[0].name = " DiskOnChip IPL / Media Header partition"; 1309 parts[0].name = " DiskOnChip IPL / Media Header partition";
1297 parts[0].offset = 0; 1310 parts[0].offset = 0;
1298 parts[0].size = mtd->erasesize * ip->firstUnit; 1311 parts[0].size = mtd->erasesize * ip->firstUnit;
1299 numparts = 1; 1312 numparts = 1;
1300 } 1313 }
1301*/
1302 1314
1303 if (ip->flags & INFTL_BINARY) 1315 if (ip->flags & INFTL_BINARY)
1304 parts[numparts].name = " DiskOnChip BDK partition"; 1316 parts[numparts].name = " DiskOnChip BDK partition";