diff options
Diffstat (limited to 'drivers/mtd/nand/diskonchip.c')
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 96 |
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 | ||
42 | static unsigned long __initdata doc_locations[] = { | 42 | static 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. */ |
91 | static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; | 86 | static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; |
@@ -111,10 +106,11 @@ module_param(try_dword, int, 0); | |||
111 | static int no_ecc_failures=0; | 106 | static int no_ecc_failures=0; |
112 | module_param(no_ecc_failures, int, 0); | 107 | module_param(no_ecc_failures, int, 0); |
113 | 108 | ||
114 | #ifdef CONFIG_MTD_PARTITIONS | ||
115 | static int no_autopart=0; | 109 | static int no_autopart=0; |
116 | module_param(no_autopart, int, 0); | 110 | module_param(no_autopart, int, 0); |
117 | #endif | 111 | |
112 | static int show_firmware_partition=0; | ||
113 | module_param(show_firmware_partition, int, 0); | ||
118 | 114 | ||
119 | #ifdef MTD_NAND_DISKONCHIP_BBTWRITE | 115 | #ifdef MTD_NAND_DISKONCHIP_BBTWRITE |
120 | static int inftl_bbt_write=1; | 116 | static int inftl_bbt_write=1; |
@@ -123,7 +119,7 @@ static int inftl_bbt_write=0; | |||
123 | #endif | 119 | #endif |
124 | module_param(inftl_bbt_write, int, 0); | 120 | module_param(inftl_bbt_write, int, 0); |
125 | 121 | ||
126 | static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; | 122 | static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS; |
127 | module_param(doc_config_location, ulong, 0); | 123 | module_param(doc_config_location, ulong, 0); |
128 | MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); | 124 | MODULE_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 | */ | ||
1049 | static struct nand_oobinfo doc200x_oobinfo = { | 1062 | static 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; | ||
1195 | out: | 1214 | out: |
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"; |