diff options
Diffstat (limited to 'drivers/mtd/chips/cfi_cmdset_0001.c')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 2f19fa78d24a..3aa3dca56ae6 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
526 | struct cfi_pri_intelext *extp = cfi->cmdset_priv; | 526 | struct cfi_pri_intelext *extp = cfi->cmdset_priv; |
527 | 527 | ||
528 | /* | 528 | /* |
529 | * Probing of multi-partition flash ships. | 529 | * Probing of multi-partition flash chips. |
530 | * | 530 | * |
531 | * To support multiple partitions when available, we simply arrange | 531 | * To support multiple partitions when available, we simply arrange |
532 | * for each of them to have their own flchip structure even if they | 532 | * for each of them to have their own flchip structure even if they |
@@ -653,7 +653,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
653 | resettime: | 653 | resettime: |
654 | timeo = jiffies + HZ; | 654 | timeo = jiffies + HZ; |
655 | retry: | 655 | retry: |
656 | if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE)) { | 656 | if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { |
657 | /* | 657 | /* |
658 | * OK. We have possibility for contension on the write/erase | 658 | * OK. We have possibility for contension on the write/erase |
659 | * operations which are global to the real chip and not per | 659 | * operations which are global to the real chip and not per |
@@ -798,6 +798,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
798 | if (mode == FL_READY && chip->oldstate == FL_READY) | 798 | if (mode == FL_READY && chip->oldstate == FL_READY) |
799 | return 0; | 799 | return 0; |
800 | 800 | ||
801 | case FL_SHUTDOWN: | ||
802 | /* The machine is rebooting now,so no one can get chip anymore */ | ||
803 | return -EIO; | ||
801 | default: | 804 | default: |
802 | sleep: | 805 | sleep: |
803 | set_current_state(TASK_UNINTERRUPTIBLE); | 806 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -1166,28 +1169,34 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si | |||
1166 | { | 1169 | { |
1167 | struct map_info *map = mtd->priv; | 1170 | struct map_info *map = mtd->priv; |
1168 | struct cfi_private *cfi = map->fldrv_priv; | 1171 | struct cfi_private *cfi = map->fldrv_priv; |
1169 | unsigned long ofs; | 1172 | unsigned long ofs, last_end = 0; |
1170 | int chipnum; | 1173 | int chipnum; |
1171 | int ret = 0; | 1174 | int ret = 0; |
1172 | 1175 | ||
1173 | if (!map->virt || (from + len > mtd->size)) | 1176 | if (!map->virt || (from + len > mtd->size)) |
1174 | return -EINVAL; | 1177 | return -EINVAL; |
1175 | 1178 | ||
1176 | *mtdbuf = (void *)map->virt + from; | ||
1177 | *retlen = 0; | ||
1178 | |||
1179 | /* Now lock the chip(s) to POINT state */ | 1179 | /* Now lock the chip(s) to POINT state */ |
1180 | 1180 | ||
1181 | /* ofs: offset within the first chip that the first read should start */ | 1181 | /* ofs: offset within the first chip that the first read should start */ |
1182 | chipnum = (from >> cfi->chipshift); | 1182 | chipnum = (from >> cfi->chipshift); |
1183 | ofs = from - (chipnum << cfi->chipshift); | 1183 | ofs = from - (chipnum << cfi->chipshift); |
1184 | 1184 | ||
1185 | *mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs; | ||
1186 | *retlen = 0; | ||
1187 | |||
1185 | while (len) { | 1188 | while (len) { |
1186 | unsigned long thislen; | 1189 | unsigned long thislen; |
1187 | 1190 | ||
1188 | if (chipnum >= cfi->numchips) | 1191 | if (chipnum >= cfi->numchips) |
1189 | break; | 1192 | break; |
1190 | 1193 | ||
1194 | /* We cannot point across chips that are virtually disjoint */ | ||
1195 | if (!last_end) | ||
1196 | last_end = cfi->chips[chipnum].start; | ||
1197 | else if (cfi->chips[chipnum].start != last_end) | ||
1198 | break; | ||
1199 | |||
1191 | if ((len + ofs -1) >> cfi->chipshift) | 1200 | if ((len + ofs -1) >> cfi->chipshift) |
1192 | thislen = (1<<cfi->chipshift) - ofs; | 1201 | thislen = (1<<cfi->chipshift) - ofs; |
1193 | else | 1202 | else |
@@ -1201,6 +1210,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si | |||
1201 | len -= thislen; | 1210 | len -= thislen; |
1202 | 1211 | ||
1203 | ofs = 0; | 1212 | ofs = 0; |
1213 | last_end += 1 << cfi->chipshift; | ||
1204 | chipnum++; | 1214 | chipnum++; |
1205 | } | 1215 | } |
1206 | return 0; | 1216 | return 0; |
@@ -1780,7 +1790,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1780 | return ret; | 1790 | return ret; |
1781 | } | 1791 | } |
1782 | 1792 | ||
1783 | int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) | 1793 | static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) |
1784 | { | 1794 | { |
1785 | unsigned long ofs, len; | 1795 | unsigned long ofs, len; |
1786 | int ret; | 1796 | int ret; |
@@ -1930,7 +1940,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
1930 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", | 1940 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", |
1931 | __FUNCTION__, ofs, len); | 1941 | __FUNCTION__, ofs, len); |
1932 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 1942 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
1933 | ofs, len, 0); | 1943 | ofs, len, NULL); |
1934 | #endif | 1944 | #endif |
1935 | 1945 | ||
1936 | ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, | 1946 | ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, |
@@ -1940,7 +1950,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
1940 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", | 1950 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", |
1941 | __FUNCTION__, ret); | 1951 | __FUNCTION__, ret); |
1942 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 1952 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
1943 | ofs, len, 0); | 1953 | ofs, len, NULL); |
1944 | #endif | 1954 | #endif |
1945 | 1955 | ||
1946 | return ret; | 1956 | return ret; |
@@ -1954,7 +1964,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
1954 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", | 1964 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", |
1955 | __FUNCTION__, ofs, len); | 1965 | __FUNCTION__, ofs, len); |
1956 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 1966 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
1957 | ofs, len, 0); | 1967 | ofs, len, NULL); |
1958 | #endif | 1968 | #endif |
1959 | 1969 | ||
1960 | ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, | 1970 | ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, |
@@ -1964,7 +1974,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
1964 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", | 1974 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", |
1965 | __FUNCTION__, ret); | 1975 | __FUNCTION__, ret); |
1966 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 1976 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
1967 | ofs, len, 0); | 1977 | ofs, len, NULL); |
1968 | #endif | 1978 | #endif |
1969 | 1979 | ||
1970 | return ret; | 1980 | return ret; |
@@ -2255,7 +2265,7 @@ static void cfi_intelext_save_locks(struct mtd_info *mtd) | |||
2255 | adr = region->offset + block * len; | 2265 | adr = region->offset + block * len; |
2256 | 2266 | ||
2257 | status = cfi_varsize_frob(mtd, | 2267 | status = cfi_varsize_frob(mtd, |
2258 | do_getlockstatus_oneblock, adr, len, 0); | 2268 | do_getlockstatus_oneblock, adr, len, NULL); |
2259 | if (status) | 2269 | if (status) |
2260 | set_bit(block, region->lockmap); | 2270 | set_bit(block, region->lockmap); |
2261 | else | 2271 | else |
@@ -2402,10 +2412,10 @@ static int cfi_intelext_reset(struct mtd_info *mtd) | |||
2402 | and switch to array mode so any bootloader in | 2412 | and switch to array mode so any bootloader in |
2403 | flash is accessible for soft reboot. */ | 2413 | flash is accessible for soft reboot. */ |
2404 | spin_lock(chip->mutex); | 2414 | spin_lock(chip->mutex); |
2405 | ret = get_chip(map, chip, chip->start, FL_SYNCING); | 2415 | ret = get_chip(map, chip, chip->start, FL_SHUTDOWN); |
2406 | if (!ret) { | 2416 | if (!ret) { |
2407 | map_write(map, CMD(0xff), chip->start); | 2417 | map_write(map, CMD(0xff), chip->start); |
2408 | chip->state = FL_READY; | 2418 | chip->state = FL_SHUTDOWN; |
2409 | } | 2419 | } |
2410 | spin_unlock(chip->mutex); | 2420 | spin_unlock(chip->mutex); |
2411 | } | 2421 | } |