diff options
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r-- | drivers/mtd/chips/Kconfig | 4 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 71 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 52 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_probe.c | 58 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_util.c | 66 | ||||
-rw-r--r-- | drivers/mtd/chips/gen_probe.c | 2 |
6 files changed, 178 insertions, 75 deletions
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 479d32b57a1e..9408099eec48 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -6,6 +6,7 @@ menu "RAM/ROM/Flash chip drivers" | |||
6 | config MTD_CFI | 6 | config MTD_CFI |
7 | tristate "Detect flash chips by Common Flash Interface (CFI) probe" | 7 | tristate "Detect flash chips by Common Flash Interface (CFI) probe" |
8 | select MTD_GEN_PROBE | 8 | select MTD_GEN_PROBE |
9 | select MTD_CFI_UTIL | ||
9 | help | 10 | help |
10 | The Common Flash Interface specification was developed by Intel, | 11 | The Common Flash Interface specification was developed by Intel, |
11 | AMD and other flash manufactures that provides a universal method | 12 | AMD and other flash manufactures that provides a universal method |
@@ -154,6 +155,7 @@ config MTD_CFI_I8 | |||
154 | config MTD_OTP | 155 | config MTD_OTP |
155 | bool "Protection Registers aka one-time programmable (OTP) bits" | 156 | bool "Protection Registers aka one-time programmable (OTP) bits" |
156 | depends on MTD_CFI_ADV_OPTIONS | 157 | depends on MTD_CFI_ADV_OPTIONS |
158 | select HAVE_MTD_OTP | ||
157 | default n | 159 | default n |
158 | help | 160 | help |
159 | This enables support for reading, writing and locking so called | 161 | This enables support for reading, writing and locking so called |
@@ -187,7 +189,7 @@ config MTD_CFI_INTELEXT | |||
187 | StrataFlash and other parts. | 189 | StrataFlash and other parts. |
188 | 190 | ||
189 | config MTD_CFI_AMDSTD | 191 | config MTD_CFI_AMDSTD |
190 | tristate "Support for AMD/Fujitsu flash chips" | 192 | tristate "Support for AMD/Fujitsu/Spansion flash chips" |
191 | depends on MTD_GEN_PROBE | 193 | depends on MTD_GEN_PROBE |
192 | select MTD_CFI_UTIL | 194 | select MTD_CFI_UTIL |
193 | help | 195 | help |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 5f1b472137a0..c93a8be5d5f1 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -478,6 +478,28 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
478 | else | 478 | else |
479 | cfi->chips[i].erase_time = 2000000; | 479 | cfi->chips[i].erase_time = 2000000; |
480 | 480 | ||
481 | if (cfi->cfiq->WordWriteTimeoutTyp && | ||
482 | cfi->cfiq->WordWriteTimeoutMax) | ||
483 | cfi->chips[i].word_write_time_max = | ||
484 | 1<<(cfi->cfiq->WordWriteTimeoutTyp + | ||
485 | cfi->cfiq->WordWriteTimeoutMax); | ||
486 | else | ||
487 | cfi->chips[i].word_write_time_max = 50000 * 8; | ||
488 | |||
489 | if (cfi->cfiq->BufWriteTimeoutTyp && | ||
490 | cfi->cfiq->BufWriteTimeoutMax) | ||
491 | cfi->chips[i].buffer_write_time_max = | ||
492 | 1<<(cfi->cfiq->BufWriteTimeoutTyp + | ||
493 | cfi->cfiq->BufWriteTimeoutMax); | ||
494 | |||
495 | if (cfi->cfiq->BlockEraseTimeoutTyp && | ||
496 | cfi->cfiq->BlockEraseTimeoutMax) | ||
497 | cfi->chips[i].erase_time_max = | ||
498 | 1000<<(cfi->cfiq->BlockEraseTimeoutTyp + | ||
499 | cfi->cfiq->BlockEraseTimeoutMax); | ||
500 | else | ||
501 | cfi->chips[i].erase_time_max = 2000000 * 8; | ||
502 | |||
481 | cfi->chips[i].ref_point_counter = 0; | 503 | cfi->chips[i].ref_point_counter = 0; |
482 | init_waitqueue_head(&(cfi->chips[i].wq)); | 504 | init_waitqueue_head(&(cfi->chips[i].wq)); |
483 | } | 505 | } |
@@ -703,6 +725,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long | |||
703 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; | 725 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; |
704 | unsigned long timeo = jiffies + HZ; | 726 | unsigned long timeo = jiffies + HZ; |
705 | 727 | ||
728 | /* Prevent setting state FL_SYNCING for chip in suspended state. */ | ||
729 | if (mode == FL_SYNCING && chip->oldstate != FL_READY) | ||
730 | goto sleep; | ||
731 | |||
706 | switch (chip->state) { | 732 | switch (chip->state) { |
707 | 733 | ||
708 | case FL_STATUS: | 734 | case FL_STATUS: |
@@ -808,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
808 | DECLARE_WAITQUEUE(wait, current); | 834 | DECLARE_WAITQUEUE(wait, current); |
809 | 835 | ||
810 | retry: | 836 | retry: |
811 | if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING | 837 | if (chip->priv && |
812 | || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { | 838 | (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE |
839 | || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) { | ||
813 | /* | 840 | /* |
814 | * OK. We have possibility for contention on the write/erase | 841 | * OK. We have possibility for contention on the write/erase |
815 | * operations which are global to the real chip and not per | 842 | * operations which are global to the real chip and not per |
@@ -859,6 +886,14 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
859 | return ret; | 886 | return ret; |
860 | } | 887 | } |
861 | spin_lock(&shared->lock); | 888 | spin_lock(&shared->lock); |
889 | |||
890 | /* We should not own chip if it is already | ||
891 | * in FL_SYNCING state. Put contender and retry. */ | ||
892 | if (chip->state == FL_SYNCING) { | ||
893 | put_chip(map, contender, contender->start); | ||
894 | spin_unlock(contender->mutex); | ||
895 | goto retry; | ||
896 | } | ||
862 | spin_unlock(contender->mutex); | 897 | spin_unlock(contender->mutex); |
863 | } | 898 | } |
864 | 899 | ||
@@ -1012,7 +1047,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip, | |||
1012 | 1047 | ||
1013 | static int __xipram xip_wait_for_operation( | 1048 | static int __xipram xip_wait_for_operation( |
1014 | struct map_info *map, struct flchip *chip, | 1049 | struct map_info *map, struct flchip *chip, |
1015 | unsigned long adr, unsigned int chip_op_time ) | 1050 | unsigned long adr, unsigned int chip_op_time_max) |
1016 | { | 1051 | { |
1017 | struct cfi_private *cfi = map->fldrv_priv; | 1052 | struct cfi_private *cfi = map->fldrv_priv; |
1018 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; | 1053 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; |
@@ -1021,7 +1056,7 @@ static int __xipram xip_wait_for_operation( | |||
1021 | flstate_t oldstate, newstate; | 1056 | flstate_t oldstate, newstate; |
1022 | 1057 | ||
1023 | start = xip_currtime(); | 1058 | start = xip_currtime(); |
1024 | usec = chip_op_time * 8; | 1059 | usec = chip_op_time_max; |
1025 | if (usec == 0) | 1060 | if (usec == 0) |
1026 | usec = 500000; | 1061 | usec = 500000; |
1027 | done = 0; | 1062 | done = 0; |
@@ -1131,8 +1166,8 @@ static int __xipram xip_wait_for_operation( | |||
1131 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ | 1166 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ |
1132 | INVALIDATE_CACHED_RANGE(map, from, size) | 1167 | INVALIDATE_CACHED_RANGE(map, from, size) |
1133 | 1168 | ||
1134 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ | 1169 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \ |
1135 | xip_wait_for_operation(map, chip, cmd_adr, usec) | 1170 | xip_wait_for_operation(map, chip, cmd_adr, usec_max) |
1136 | 1171 | ||
1137 | #else | 1172 | #else |
1138 | 1173 | ||
@@ -1144,7 +1179,7 @@ static int __xipram xip_wait_for_operation( | |||
1144 | static int inval_cache_and_wait_for_operation( | 1179 | static int inval_cache_and_wait_for_operation( |
1145 | struct map_info *map, struct flchip *chip, | 1180 | struct map_info *map, struct flchip *chip, |
1146 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, | 1181 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, |
1147 | unsigned int chip_op_time) | 1182 | unsigned int chip_op_time, unsigned int chip_op_time_max) |
1148 | { | 1183 | { |
1149 | struct cfi_private *cfi = map->fldrv_priv; | 1184 | struct cfi_private *cfi = map->fldrv_priv; |
1150 | map_word status, status_OK = CMD(0x80); | 1185 | map_word status, status_OK = CMD(0x80); |
@@ -1156,8 +1191,7 @@ static int inval_cache_and_wait_for_operation( | |||
1156 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); | 1191 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); |
1157 | spin_lock(chip->mutex); | 1192 | spin_lock(chip->mutex); |
1158 | 1193 | ||
1159 | /* set our timeout to 8 times the expected delay */ | 1194 | timeo = chip_op_time_max; |
1160 | timeo = chip_op_time * 8; | ||
1161 | if (!timeo) | 1195 | if (!timeo) |
1162 | timeo = 500000; | 1196 | timeo = 500000; |
1163 | reset_timeo = timeo; | 1197 | reset_timeo = timeo; |
@@ -1217,8 +1251,8 @@ static int inval_cache_and_wait_for_operation( | |||
1217 | 1251 | ||
1218 | #endif | 1252 | #endif |
1219 | 1253 | ||
1220 | #define WAIT_TIMEOUT(map, chip, adr, udelay) \ | 1254 | #define WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max) \ |
1221 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); | 1255 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay_max); |
1222 | 1256 | ||
1223 | 1257 | ||
1224 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) | 1258 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) |
@@ -1452,7 +1486,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1452 | 1486 | ||
1453 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1487 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1454 | adr, map_bankwidth(map), | 1488 | adr, map_bankwidth(map), |
1455 | chip->word_write_time); | 1489 | chip->word_write_time, |
1490 | chip->word_write_time_max); | ||
1456 | if (ret) { | 1491 | if (ret) { |
1457 | xip_enable(map, chip, adr); | 1492 | xip_enable(map, chip, adr); |
1458 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); | 1493 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); |
@@ -1623,7 +1658,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1623 | 1658 | ||
1624 | chip->state = FL_WRITING_TO_BUFFER; | 1659 | chip->state = FL_WRITING_TO_BUFFER; |
1625 | map_write(map, write_cmd, cmd_adr); | 1660 | map_write(map, write_cmd, cmd_adr); |
1626 | ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0); | 1661 | ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0, 0); |
1627 | if (ret) { | 1662 | if (ret) { |
1628 | /* Argh. Not ready for write to buffer */ | 1663 | /* Argh. Not ready for write to buffer */ |
1629 | map_word Xstatus = map_read(map, cmd_adr); | 1664 | map_word Xstatus = map_read(map, cmd_adr); |
@@ -1640,7 +1675,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1640 | 1675 | ||
1641 | /* Figure out the number of words to write */ | 1676 | /* Figure out the number of words to write */ |
1642 | word_gap = (-adr & (map_bankwidth(map)-1)); | 1677 | word_gap = (-adr & (map_bankwidth(map)-1)); |
1643 | words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map); | 1678 | words = DIV_ROUND_UP(len - word_gap, map_bankwidth(map)); |
1644 | if (!word_gap) { | 1679 | if (!word_gap) { |
1645 | words--; | 1680 | words--; |
1646 | } else { | 1681 | } else { |
@@ -1692,7 +1727,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1692 | 1727 | ||
1693 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, | 1728 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, |
1694 | initial_adr, initial_len, | 1729 | initial_adr, initial_len, |
1695 | chip->buffer_write_time); | 1730 | chip->buffer_write_time, |
1731 | chip->buffer_write_time_max); | ||
1696 | if (ret) { | 1732 | if (ret) { |
1697 | map_write(map, CMD(0x70), cmd_adr); | 1733 | map_write(map, CMD(0x70), cmd_adr); |
1698 | chip->state = FL_STATUS; | 1734 | chip->state = FL_STATUS; |
@@ -1827,7 +1863,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1827 | 1863 | ||
1828 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1864 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1829 | adr, len, | 1865 | adr, len, |
1830 | chip->erase_time); | 1866 | chip->erase_time, |
1867 | chip->erase_time_max); | ||
1831 | if (ret) { | 1868 | if (ret) { |
1832 | map_write(map, CMD(0x70), adr); | 1869 | map_write(map, CMD(0x70), adr); |
1833 | chip->state = FL_STATUS; | 1870 | chip->state = FL_STATUS; |
@@ -2006,7 +2043,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip | |||
2006 | */ | 2043 | */ |
2007 | udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; | 2044 | udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; |
2008 | 2045 | ||
2009 | ret = WAIT_TIMEOUT(map, chip, adr, udelay); | 2046 | ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100); |
2010 | if (ret) { | 2047 | if (ret) { |
2011 | map_write(map, CMD(0x70), adr); | 2048 | map_write(map, CMD(0x70), adr); |
2012 | chip->state = FL_STATUS; | 2049 | chip->state = FL_STATUS; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a972cc6be436..3e6f5d8609e8 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -13,6 +13,8 @@ | |||
13 | * XIP support hooks by Vitaly Wool (based on code for Intel flash | 13 | * XIP support hooks by Vitaly Wool (based on code for Intel flash |
14 | * by Nicolas Pitre) | 14 | * by Nicolas Pitre) |
15 | * | 15 | * |
16 | * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0 | ||
17 | * | ||
16 | * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com | 18 | * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com |
17 | * | 19 | * |
18 | * This code is GPL | 20 | * This code is GPL |
@@ -43,6 +45,7 @@ | |||
43 | 45 | ||
44 | #define MANUFACTURER_AMD 0x0001 | 46 | #define MANUFACTURER_AMD 0x0001 |
45 | #define MANUFACTURER_ATMEL 0x001F | 47 | #define MANUFACTURER_ATMEL 0x001F |
48 | #define MANUFACTURER_MACRONIX 0x00C2 | ||
46 | #define MANUFACTURER_SST 0x00BF | 49 | #define MANUFACTURER_SST 0x00BF |
47 | #define SST49LF004B 0x0060 | 50 | #define SST49LF004B 0x0060 |
48 | #define SST49LF040B 0x0050 | 51 | #define SST49LF040B 0x0050 |
@@ -144,12 +147,44 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) | |||
144 | 147 | ||
145 | if (((major << 8) | minor) < 0x3131) { | 148 | if (((major << 8) | minor) < 0x3131) { |
146 | /* CFI version 1.0 => don't trust bootloc */ | 149 | /* CFI version 1.0 => don't trust bootloc */ |
150 | |||
151 | DEBUG(MTD_DEBUG_LEVEL1, | ||
152 | "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", | ||
153 | map->name, cfi->mfr, cfi->id); | ||
154 | |||
155 | /* AFAICS all 29LV400 with a bottom boot block have a device ID | ||
156 | * of 0x22BA in 16-bit mode and 0xBA in 8-bit mode. | ||
157 | * These were badly detected as they have the 0x80 bit set | ||
158 | * so treat them as a special case. | ||
159 | */ | ||
160 | if (((cfi->id == 0xBA) || (cfi->id == 0x22BA)) && | ||
161 | |||
162 | /* Macronix added CFI to their 2nd generation | ||
163 | * MX29LV400C B/T but AFAICS no other 29LV400 (AMD, | ||
164 | * Fujitsu, Spansion, EON, ESI and older Macronix) | ||
165 | * has CFI. | ||
166 | * | ||
167 | * Therefore also check the manufacturer. | ||
168 | * This reduces the risk of false detection due to | ||
169 | * the 8-bit device ID. | ||
170 | */ | ||
171 | (cfi->mfr == MANUFACTURER_MACRONIX)) { | ||
172 | DEBUG(MTD_DEBUG_LEVEL1, | ||
173 | "%s: Macronix MX29LV400C with bottom boot block" | ||
174 | " detected\n", map->name); | ||
175 | extp->TopBottom = 2; /* bottom boot */ | ||
176 | } else | ||
147 | if (cfi->id & 0x80) { | 177 | if (cfi->id & 0x80) { |
148 | printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); | 178 | printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); |
149 | extp->TopBottom = 3; /* top boot */ | 179 | extp->TopBottom = 3; /* top boot */ |
150 | } else { | 180 | } else { |
151 | extp->TopBottom = 2; /* bottom boot */ | 181 | extp->TopBottom = 2; /* bottom boot */ |
152 | } | 182 | } |
183 | |||
184 | DEBUG(MTD_DEBUG_LEVEL1, | ||
185 | "%s: AMD CFI PRI V%c.%c has no boot block field;" | ||
186 | " deduced %s from Device ID\n", map->name, major, minor, | ||
187 | extp->TopBottom == 2 ? "bottom" : "top"); | ||
153 | } | 188 | } |
154 | } | 189 | } |
155 | #endif | 190 | #endif |
@@ -178,10 +213,18 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | |||
178 | if (atmel_pri.Features & 0x02) | 213 | if (atmel_pri.Features & 0x02) |
179 | extp->EraseSuspend = 2; | 214 | extp->EraseSuspend = 2; |
180 | 215 | ||
181 | if (atmel_pri.BottomBoot) | 216 | /* Some chips got it backwards... */ |
182 | extp->TopBottom = 2; | 217 | if (cfi->id == AT49BV6416) { |
183 | else | 218 | if (atmel_pri.BottomBoot) |
184 | extp->TopBottom = 3; | 219 | extp->TopBottom = 3; |
220 | else | ||
221 | extp->TopBottom = 2; | ||
222 | } else { | ||
223 | if (atmel_pri.BottomBoot) | ||
224 | extp->TopBottom = 2; | ||
225 | else | ||
226 | extp->TopBottom = 3; | ||
227 | } | ||
185 | 228 | ||
186 | /* burst write mode not supported */ | 229 | /* burst write mode not supported */ |
187 | cfi->cfiq->BufWriteTimeoutTyp = 0; | 230 | cfi->cfiq->BufWriteTimeoutTyp = 0; |
@@ -243,6 +286,7 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
243 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, | 286 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, |
244 | #ifdef AMD_BOOTLOC_BUG | 287 | #ifdef AMD_BOOTLOC_BUG |
245 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | 288 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, |
289 | { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | ||
246 | #endif | 290 | #endif |
247 | { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, | 291 | { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, |
248 | { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, }, | 292 | { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, }, |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index c418e92e1d92..e63e6749429a 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -44,17 +44,14 @@ do { \ | |||
44 | 44 | ||
45 | #define xip_enable(base, map, cfi) \ | 45 | #define xip_enable(base, map, cfi) \ |
46 | do { \ | 46 | do { \ |
47 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \ | 47 | cfi_qry_mode_off(base, map, cfi); \ |
48 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \ | ||
49 | xip_allowed(base, map); \ | 48 | xip_allowed(base, map); \ |
50 | } while (0) | 49 | } while (0) |
51 | 50 | ||
52 | #define xip_disable_qry(base, map, cfi) \ | 51 | #define xip_disable_qry(base, map, cfi) \ |
53 | do { \ | 52 | do { \ |
54 | xip_disable(); \ | 53 | xip_disable(); \ |
55 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \ | 54 | cfi_qry_mode_on(base, map, cfi); \ |
56 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \ | ||
57 | cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \ | ||
58 | } while (0) | 55 | } while (0) |
59 | 56 | ||
60 | #else | 57 | #else |
@@ -70,32 +67,6 @@ do { \ | |||
70 | in: interleave,type,mode | 67 | in: interleave,type,mode |
71 | ret: table index, <0 for error | 68 | ret: table index, <0 for error |
72 | */ | 69 | */ |
73 | static int __xipram qry_present(struct map_info *map, __u32 base, | ||
74 | struct cfi_private *cfi) | ||
75 | { | ||
76 | int osf = cfi->interleave * cfi->device_type; // scale factor | ||
77 | map_word val[3]; | ||
78 | map_word qry[3]; | ||
79 | |||
80 | qry[0] = cfi_build_cmd('Q', map, cfi); | ||
81 | qry[1] = cfi_build_cmd('R', map, cfi); | ||
82 | qry[2] = cfi_build_cmd('Y', map, cfi); | ||
83 | |||
84 | val[0] = map_read(map, base + osf*0x10); | ||
85 | val[1] = map_read(map, base + osf*0x11); | ||
86 | val[2] = map_read(map, base + osf*0x12); | ||
87 | |||
88 | if (!map_word_equal(map, qry[0], val[0])) | ||
89 | return 0; | ||
90 | |||
91 | if (!map_word_equal(map, qry[1], val[1])) | ||
92 | return 0; | ||
93 | |||
94 | if (!map_word_equal(map, qry[2], val[2])) | ||
95 | return 0; | ||
96 | |||
97 | return 1; // "QRY" found | ||
98 | } | ||
99 | 70 | ||
100 | static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, | 71 | static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, |
101 | unsigned long *chip_map, struct cfi_private *cfi) | 72 | unsigned long *chip_map, struct cfi_private *cfi) |
@@ -116,11 +87,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, | |||
116 | } | 87 | } |
117 | 88 | ||
118 | xip_disable(); | 89 | xip_disable(); |
119 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | 90 | if (!cfi_qry_mode_on(base, map, cfi)) { |
120 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); | ||
121 | cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); | ||
122 | |||
123 | if (!qry_present(map,base,cfi)) { | ||
124 | xip_enable(base, map, cfi); | 91 | xip_enable(base, map, cfi); |
125 | return 0; | 92 | return 0; |
126 | } | 93 | } |
@@ -141,14 +108,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, | |||
141 | start = i << cfi->chipshift; | 108 | start = i << cfi->chipshift; |
142 | /* This chip should be in read mode if it's one | 109 | /* This chip should be in read mode if it's one |
143 | we've already touched. */ | 110 | we've already touched. */ |
144 | if (qry_present(map, start, cfi)) { | 111 | if (cfi_qry_present(map, start, cfi)) { |
145 | /* Eep. This chip also had the QRY marker. | 112 | /* Eep. This chip also had the QRY marker. |
146 | * Is it an alias for the new one? */ | 113 | * Is it an alias for the new one? */ |
147 | cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL); | 114 | cfi_qry_mode_off(start, map, cfi); |
148 | cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL); | ||
149 | 115 | ||
150 | /* If the QRY marker goes away, it's an alias */ | 116 | /* If the QRY marker goes away, it's an alias */ |
151 | if (!qry_present(map, start, cfi)) { | 117 | if (!cfi_qry_present(map, start, cfi)) { |
152 | xip_allowed(base, map); | 118 | xip_allowed(base, map); |
153 | printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", | 119 | printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", |
154 | map->name, base, start); | 120 | map->name, base, start); |
@@ -158,10 +124,9 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, | |||
158 | * unfortunate. Stick the new chip in read mode | 124 | * unfortunate. Stick the new chip in read mode |
159 | * too and if it's the same, assume it's an alias. */ | 125 | * too and if it's the same, assume it's an alias. */ |
160 | /* FIXME: Use other modes to do a proper check */ | 126 | /* FIXME: Use other modes to do a proper check */ |
161 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | 127 | cfi_qry_mode_off(base, map, cfi); |
162 | cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL); | ||
163 | 128 | ||
164 | if (qry_present(map, base, cfi)) { | 129 | if (cfi_qry_present(map, base, cfi)) { |
165 | xip_allowed(base, map); | 130 | xip_allowed(base, map); |
166 | printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", | 131 | printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", |
167 | map->name, base, start); | 132 | map->name, base, start); |
@@ -176,8 +141,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, | |||
176 | cfi->numchips++; | 141 | cfi->numchips++; |
177 | 142 | ||
178 | /* Put it back into Read Mode */ | 143 | /* Put it back into Read Mode */ |
179 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | 144 | cfi_qry_mode_off(base, map, cfi); |
180 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); | ||
181 | xip_allowed(base, map); | 145 | xip_allowed(base, map); |
182 | 146 | ||
183 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", | 147 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", |
@@ -237,9 +201,7 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
237 | cfi_read_query(map, base + 0xf * ofs_factor); | 201 | cfi_read_query(map, base + 0xf * ofs_factor); |
238 | 202 | ||
239 | /* Put it back into Read Mode */ | 203 | /* Put it back into Read Mode */ |
240 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | 204 | cfi_qry_mode_off(base, map, cfi); |
241 | /* ... even if it's an Intel chip */ | ||
242 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); | ||
243 | xip_allowed(base, map); | 205 | xip_allowed(base, map); |
244 | 206 | ||
245 | /* Do any necessary byteswapping */ | 207 | /* Do any necessary byteswapping */ |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 0ee457018016..34d40e25d312 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -24,6 +24,66 @@ | |||
24 | #include <linux/mtd/cfi.h> | 24 | #include <linux/mtd/cfi.h> |
25 | #include <linux/mtd/compatmac.h> | 25 | #include <linux/mtd/compatmac.h> |
26 | 26 | ||
27 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, | ||
28 | struct cfi_private *cfi) | ||
29 | { | ||
30 | int osf = cfi->interleave * cfi->device_type; /* scale factor */ | ||
31 | map_word val[3]; | ||
32 | map_word qry[3]; | ||
33 | |||
34 | qry[0] = cfi_build_cmd('Q', map, cfi); | ||
35 | qry[1] = cfi_build_cmd('R', map, cfi); | ||
36 | qry[2] = cfi_build_cmd('Y', map, cfi); | ||
37 | |||
38 | val[0] = map_read(map, base + osf*0x10); | ||
39 | val[1] = map_read(map, base + osf*0x11); | ||
40 | val[2] = map_read(map, base + osf*0x12); | ||
41 | |||
42 | if (!map_word_equal(map, qry[0], val[0])) | ||
43 | return 0; | ||
44 | |||
45 | if (!map_word_equal(map, qry[1], val[1])) | ||
46 | return 0; | ||
47 | |||
48 | if (!map_word_equal(map, qry[2], val[2])) | ||
49 | return 0; | ||
50 | |||
51 | return 1; /* "QRY" found */ | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(cfi_qry_present); | ||
54 | |||
55 | int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map, | ||
56 | struct cfi_private *cfi) | ||
57 | { | ||
58 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
59 | cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); | ||
60 | if (cfi_qry_present(map, base, cfi)) | ||
61 | return 1; | ||
62 | /* QRY not found probably we deal with some odd CFI chips */ | ||
63 | /* Some revisions of some old Intel chips? */ | ||
64 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
65 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); | ||
66 | cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); | ||
67 | if (cfi_qry_present(map, base, cfi)) | ||
68 | return 1; | ||
69 | /* ST M29DW chips */ | ||
70 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
71 | cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
72 | if (cfi_qry_present(map, base, cfi)) | ||
73 | return 1; | ||
74 | /* QRY not found */ | ||
75 | return 0; | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(cfi_qry_mode_on); | ||
78 | |||
79 | void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map, | ||
80 | struct cfi_private *cfi) | ||
81 | { | ||
82 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
83 | cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); | ||
84 | } | ||
85 | EXPORT_SYMBOL_GPL(cfi_qry_mode_off); | ||
86 | |||
27 | struct cfi_extquery * | 87 | struct cfi_extquery * |
28 | __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) | 88 | __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) |
29 | { | 89 | { |
@@ -48,8 +108,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n | |||
48 | #endif | 108 | #endif |
49 | 109 | ||
50 | /* Switch it into Query Mode */ | 110 | /* Switch it into Query Mode */ |
51 | cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); | 111 | cfi_qry_mode_on(base, map, cfi); |
52 | |||
53 | /* Read in the Extended Query Table */ | 112 | /* Read in the Extended Query Table */ |
54 | for (i=0; i<size; i++) { | 113 | for (i=0; i<size; i++) { |
55 | ((unsigned char *)extp)[i] = | 114 | ((unsigned char *)extp)[i] = |
@@ -57,8 +116,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n | |||
57 | } | 116 | } |
58 | 117 | ||
59 | /* Make sure it returns to read mode */ | 118 | /* Make sure it returns to read mode */ |
60 | cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL); | 119 | cfi_qry_mode_off(base, map, cfi); |
61 | cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL); | ||
62 | 120 | ||
63 | #ifdef CONFIG_MTD_XIP | 121 | #ifdef CONFIG_MTD_XIP |
64 | (void) map_read(map, base); | 122 | (void) map_read(map, base); |
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index f061885b2812..e2dc96441e05 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c | |||
@@ -111,7 +111,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi | |||
111 | max_chips = 1; | 111 | max_chips = 1; |
112 | } | 112 | } |
113 | 113 | ||
114 | mapsize = sizeof(long) * ( (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG ); | 114 | mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG); |
115 | chip_map = kzalloc(mapsize, GFP_KERNEL); | 115 | chip_map = kzalloc(mapsize, GFP_KERNEL); |
116 | if (!chip_map) { | 116 | if (!chip_map) { |
117 | printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); | 117 | printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); |