diff options
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 87 | ||||
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 111 | ||||
-rw-r--r-- | drivers/mtd/chips/jedec_probe.c | 14 | ||||
-rw-r--r-- | drivers/mtd/devices/block2mtd.c | 93 | ||||
-rw-r--r-- | drivers/mtd/devices/pmc551.c | 4 | ||||
-rw-r--r-- | drivers/mtd/maps/Kconfig | 12 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/sharpsl.c | 7 | ||||
-rw-r--r-- | fs/jffs2/nodelist.c | 6 | ||||
-rw-r--r-- | fs/jffs2/nodelist.h | 1 | ||||
-rw-r--r-- | fs/jffs2/xattr.c | 1 | ||||
-rw-r--r-- | include/linux/mtd/cfi.h | 13 |
13 files changed, 264 insertions, 93 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 39edb8250fbc..7ea49a0d5ec3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -908,7 +908,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip, | |||
908 | 908 | ||
909 | static int __xipram xip_wait_for_operation( | 909 | static int __xipram xip_wait_for_operation( |
910 | struct map_info *map, struct flchip *chip, | 910 | struct map_info *map, struct flchip *chip, |
911 | unsigned long adr, int *chip_op_time ) | 911 | unsigned long adr, unsigned int chip_op_time ) |
912 | { | 912 | { |
913 | struct cfi_private *cfi = map->fldrv_priv; | 913 | struct cfi_private *cfi = map->fldrv_priv; |
914 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; | 914 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; |
@@ -917,7 +917,7 @@ static int __xipram xip_wait_for_operation( | |||
917 | flstate_t oldstate, newstate; | 917 | flstate_t oldstate, newstate; |
918 | 918 | ||
919 | start = xip_currtime(); | 919 | start = xip_currtime(); |
920 | usec = *chip_op_time * 8; | 920 | usec = chip_op_time * 8; |
921 | if (usec == 0) | 921 | if (usec == 0) |
922 | usec = 500000; | 922 | usec = 500000; |
923 | done = 0; | 923 | done = 0; |
@@ -1027,8 +1027,8 @@ static int __xipram xip_wait_for_operation( | |||
1027 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ | 1027 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ |
1028 | INVALIDATE_CACHED_RANGE(map, from, size) | 1028 | INVALIDATE_CACHED_RANGE(map, from, size) |
1029 | 1029 | ||
1030 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ | 1030 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ |
1031 | xip_wait_for_operation(map, chip, cmd_adr, p_usec) | 1031 | xip_wait_for_operation(map, chip, cmd_adr, usec) |
1032 | 1032 | ||
1033 | #else | 1033 | #else |
1034 | 1034 | ||
@@ -1040,64 +1040,64 @@ static int __xipram xip_wait_for_operation( | |||
1040 | static int inval_cache_and_wait_for_operation( | 1040 | static int inval_cache_and_wait_for_operation( |
1041 | struct map_info *map, struct flchip *chip, | 1041 | struct map_info *map, struct flchip *chip, |
1042 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, | 1042 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, |
1043 | int *chip_op_time ) | 1043 | unsigned int chip_op_time) |
1044 | { | 1044 | { |
1045 | struct cfi_private *cfi = map->fldrv_priv; | 1045 | struct cfi_private *cfi = map->fldrv_priv; |
1046 | map_word status, status_OK = CMD(0x80); | 1046 | map_word status, status_OK = CMD(0x80); |
1047 | int z, chip_state = chip->state; | 1047 | int chip_state = chip->state; |
1048 | unsigned long timeo; | 1048 | unsigned int timeo, sleep_time; |
1049 | 1049 | ||
1050 | spin_unlock(chip->mutex); | 1050 | spin_unlock(chip->mutex); |
1051 | if (inval_len) | 1051 | if (inval_len) |
1052 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); | 1052 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); |
1053 | if (*chip_op_time) | ||
1054 | cfi_udelay(*chip_op_time); | ||
1055 | spin_lock(chip->mutex); | 1053 | spin_lock(chip->mutex); |
1056 | 1054 | ||
1057 | timeo = *chip_op_time * 8 * HZ / 1000000; | 1055 | /* set our timeout to 8 times the expected delay */ |
1058 | if (timeo < HZ/2) | 1056 | timeo = chip_op_time * 8; |
1059 | timeo = HZ/2; | 1057 | if (!timeo) |
1060 | timeo += jiffies; | 1058 | timeo = 500000; |
1059 | sleep_time = chip_op_time / 2; | ||
1061 | 1060 | ||
1062 | z = 0; | ||
1063 | for (;;) { | 1061 | for (;;) { |
1064 | if (chip->state != chip_state) { | ||
1065 | /* Someone's suspended the operation: sleep */ | ||
1066 | DECLARE_WAITQUEUE(wait, current); | ||
1067 | |||
1068 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1069 | add_wait_queue(&chip->wq, &wait); | ||
1070 | spin_unlock(chip->mutex); | ||
1071 | schedule(); | ||
1072 | remove_wait_queue(&chip->wq, &wait); | ||
1073 | timeo = jiffies + (HZ / 2); /* FIXME */ | ||
1074 | spin_lock(chip->mutex); | ||
1075 | continue; | ||
1076 | } | ||
1077 | |||
1078 | status = map_read(map, cmd_adr); | 1062 | status = map_read(map, cmd_adr); |
1079 | if (map_word_andequal(map, status, status_OK, status_OK)) | 1063 | if (map_word_andequal(map, status, status_OK, status_OK)) |
1080 | break; | 1064 | break; |
1081 | 1065 | ||
1082 | /* OK Still waiting */ | 1066 | if (!timeo) { |
1083 | if (time_after(jiffies, timeo)) { | ||
1084 | map_write(map, CMD(0x70), cmd_adr); | 1067 | map_write(map, CMD(0x70), cmd_adr); |
1085 | chip->state = FL_STATUS; | 1068 | chip->state = FL_STATUS; |
1086 | return -ETIME; | 1069 | return -ETIME; |
1087 | } | 1070 | } |
1088 | 1071 | ||
1089 | /* Latency issues. Drop the lock, wait a while and retry */ | 1072 | /* OK Still waiting. Drop the lock, wait a while and retry. */ |
1090 | z++; | ||
1091 | spin_unlock(chip->mutex); | 1073 | spin_unlock(chip->mutex); |
1092 | cfi_udelay(1); | 1074 | if (sleep_time >= 1000000/HZ) { |
1075 | /* | ||
1076 | * Half of the normal delay still remaining | ||
1077 | * can be performed with a sleeping delay instead | ||
1078 | * of busy waiting. | ||
1079 | */ | ||
1080 | msleep(sleep_time/1000); | ||
1081 | timeo -= sleep_time; | ||
1082 | sleep_time = 1000000/HZ; | ||
1083 | } else { | ||
1084 | udelay(1); | ||
1085 | cond_resched(); | ||
1086 | timeo--; | ||
1087 | } | ||
1093 | spin_lock(chip->mutex); | 1088 | spin_lock(chip->mutex); |
1094 | } | ||
1095 | 1089 | ||
1096 | if (!z) { | 1090 | if (chip->state != chip_state) { |
1097 | if (!--(*chip_op_time)) | 1091 | /* Someone's suspended the operation: sleep */ |
1098 | *chip_op_time = 1; | 1092 | DECLARE_WAITQUEUE(wait, current); |
1099 | } else if (z > 1) | 1093 | set_current_state(TASK_UNINTERRUPTIBLE); |
1100 | ++(*chip_op_time); | 1094 | add_wait_queue(&chip->wq, &wait); |
1095 | spin_unlock(chip->mutex); | ||
1096 | schedule(); | ||
1097 | remove_wait_queue(&chip->wq, &wait); | ||
1098 | spin_lock(chip->mutex); | ||
1099 | } | ||
1100 | } | ||
1101 | 1101 | ||
1102 | /* Done and happy. */ | 1102 | /* Done and happy. */ |
1103 | chip->state = FL_STATUS; | 1103 | chip->state = FL_STATUS; |
@@ -1107,8 +1107,7 @@ static int inval_cache_and_wait_for_operation( | |||
1107 | #endif | 1107 | #endif |
1108 | 1108 | ||
1109 | #define WAIT_TIMEOUT(map, chip, adr, udelay) \ | 1109 | #define WAIT_TIMEOUT(map, chip, adr, udelay) \ |
1110 | ({ int __udelay = (udelay); \ | 1110 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); |
1111 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) | ||
1112 | 1111 | ||
1113 | 1112 | ||
1114 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) | 1113 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) |
@@ -1332,7 +1331,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1332 | 1331 | ||
1333 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1332 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1334 | adr, map_bankwidth(map), | 1333 | adr, map_bankwidth(map), |
1335 | &chip->word_write_time); | 1334 | chip->word_write_time); |
1336 | if (ret) { | 1335 | if (ret) { |
1337 | xip_enable(map, chip, adr); | 1336 | xip_enable(map, chip, adr); |
1338 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); | 1337 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); |
@@ -1569,7 +1568,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1569 | 1568 | ||
1570 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, | 1569 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, |
1571 | adr, len, | 1570 | adr, len, |
1572 | &chip->buffer_write_time); | 1571 | chip->buffer_write_time); |
1573 | if (ret) { | 1572 | if (ret) { |
1574 | map_write(map, CMD(0x70), cmd_adr); | 1573 | map_write(map, CMD(0x70), cmd_adr); |
1575 | chip->state = FL_STATUS; | 1574 | chip->state = FL_STATUS; |
@@ -1704,7 +1703,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1704 | 1703 | ||
1705 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1704 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1706 | adr, len, | 1705 | adr, len, |
1707 | &chip->erase_time); | 1706 | chip->erase_time); |
1708 | if (ret) { | 1707 | if (ret) { |
1709 | map_write(map, CMD(0x70), adr); | 1708 | map_write(map, CMD(0x70), adr); |
1710 | chip->state = FL_STATUS; | 1709 | chip->state = FL_STATUS; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 9885726a16e4..ddc5bd783354 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -45,9 +45,11 @@ | |||
45 | #define MAX_WORD_RETRIES 3 | 45 | #define MAX_WORD_RETRIES 3 |
46 | 46 | ||
47 | #define MANUFACTURER_AMD 0x0001 | 47 | #define MANUFACTURER_AMD 0x0001 |
48 | #define MANUFACTURER_ATMEL 0x001F | ||
48 | #define MANUFACTURER_SST 0x00BF | 49 | #define MANUFACTURER_SST 0x00BF |
49 | #define SST49LF004B 0x0060 | 50 | #define SST49LF004B 0x0060 |
50 | #define SST49LF008A 0x005a | 51 | #define SST49LF008A 0x005a |
52 | #define AT49BV6416 0x00d6 | ||
51 | 53 | ||
52 | static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 54 | static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
53 | static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 55 | static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
@@ -68,6 +70,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
68 | static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); | 70 | static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); |
69 | #include "fwh_lock.h" | 71 | #include "fwh_lock.h" |
70 | 72 | ||
73 | static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len); | ||
74 | static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); | ||
75 | |||
71 | static struct mtd_chip_driver cfi_amdstd_chipdrv = { | 76 | static struct mtd_chip_driver cfi_amdstd_chipdrv = { |
72 | .probe = NULL, /* Not usable directly */ | 77 | .probe = NULL, /* Not usable directly */ |
73 | .destroy = cfi_amdstd_destroy, | 78 | .destroy = cfi_amdstd_destroy, |
@@ -161,6 +166,26 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) | |||
161 | } | 166 | } |
162 | } | 167 | } |
163 | 168 | ||
169 | /* Atmel chips don't use the same PRI format as AMD chips */ | ||
170 | static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) | ||
171 | { | ||
172 | struct map_info *map = mtd->priv; | ||
173 | struct cfi_private *cfi = map->fldrv_priv; | ||
174 | struct cfi_pri_amdstd *extp = cfi->cmdset_priv; | ||
175 | struct cfi_pri_atmel atmel_pri; | ||
176 | |||
177 | memcpy(&atmel_pri, extp, sizeof(atmel_pri)); | ||
178 | memset(extp + 5, 0, sizeof(*extp) - 5); | ||
179 | |||
180 | if (atmel_pri.Features & 0x02) | ||
181 | extp->EraseSuspend = 2; | ||
182 | |||
183 | if (atmel_pri.BottomBoot) | ||
184 | extp->TopBottom = 2; | ||
185 | else | ||
186 | extp->TopBottom = 3; | ||
187 | } | ||
188 | |||
164 | static void fixup_use_secsi(struct mtd_info *mtd, void *param) | 189 | static void fixup_use_secsi(struct mtd_info *mtd, void *param) |
165 | { | 190 | { |
166 | /* Setup for chips with a secsi area */ | 191 | /* Setup for chips with a secsi area */ |
@@ -179,6 +204,16 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) | |||
179 | 204 | ||
180 | } | 205 | } |
181 | 206 | ||
207 | /* | ||
208 | * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors | ||
209 | * locked by default. | ||
210 | */ | ||
211 | static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) | ||
212 | { | ||
213 | mtd->lock = cfi_atmel_lock; | ||
214 | mtd->unlock = cfi_atmel_unlock; | ||
215 | } | ||
216 | |||
182 | static struct cfi_fixup cfi_fixup_table[] = { | 217 | static struct cfi_fixup cfi_fixup_table[] = { |
183 | #ifdef AMD_BOOTLOC_BUG | 218 | #ifdef AMD_BOOTLOC_BUG |
184 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | 219 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, |
@@ -192,6 +227,7 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
192 | #if !FORCE_WORD_WRITE | 227 | #if !FORCE_WORD_WRITE |
193 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, | 228 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, |
194 | #endif | 229 | #endif |
230 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, | ||
195 | { 0, 0, NULL, NULL } | 231 | { 0, 0, NULL, NULL } |
196 | }; | 232 | }; |
197 | static struct cfi_fixup jedec_fixup_table[] = { | 233 | static struct cfi_fixup jedec_fixup_table[] = { |
@@ -207,6 +243,7 @@ static struct cfi_fixup fixup_table[] = { | |||
207 | * we know that is the case. | 243 | * we know that is the case. |
208 | */ | 244 | */ |
209 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, | 245 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, |
246 | { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, | ||
210 | { 0, 0, NULL, NULL } | 247 | { 0, 0, NULL, NULL } |
211 | }; | 248 | }; |
212 | 249 | ||
@@ -1607,6 +1644,80 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) | |||
1607 | return 0; | 1644 | return 0; |
1608 | } | 1645 | } |
1609 | 1646 | ||
1647 | static int do_atmel_lock(struct map_info *map, struct flchip *chip, | ||
1648 | unsigned long adr, int len, void *thunk) | ||
1649 | { | ||
1650 | struct cfi_private *cfi = map->fldrv_priv; | ||
1651 | int ret; | ||
1652 | |||
1653 | spin_lock(chip->mutex); | ||
1654 | ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); | ||
1655 | if (ret) | ||
1656 | goto out_unlock; | ||
1657 | chip->state = FL_LOCKING; | ||
1658 | |||
1659 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | ||
1660 | __func__, adr, len); | ||
1661 | |||
1662 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1663 | cfi->device_type, NULL); | ||
1664 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1665 | cfi->device_type, NULL); | ||
1666 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, | ||
1667 | cfi->device_type, NULL); | ||
1668 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1669 | cfi->device_type, NULL); | ||
1670 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1671 | cfi->device_type, NULL); | ||
1672 | map_write(map, CMD(0x40), chip->start + adr); | ||
1673 | |||
1674 | chip->state = FL_READY; | ||
1675 | put_chip(map, chip, adr + chip->start); | ||
1676 | ret = 0; | ||
1677 | |||
1678 | out_unlock: | ||
1679 | spin_unlock(chip->mutex); | ||
1680 | return ret; | ||
1681 | } | ||
1682 | |||
1683 | static int do_atmel_unlock(struct map_info *map, struct flchip *chip, | ||
1684 | unsigned long adr, int len, void *thunk) | ||
1685 | { | ||
1686 | struct cfi_private *cfi = map->fldrv_priv; | ||
1687 | int ret; | ||
1688 | |||
1689 | spin_lock(chip->mutex); | ||
1690 | ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING); | ||
1691 | if (ret) | ||
1692 | goto out_unlock; | ||
1693 | chip->state = FL_UNLOCKING; | ||
1694 | |||
1695 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | ||
1696 | __func__, adr, len); | ||
1697 | |||
1698 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1699 | cfi->device_type, NULL); | ||
1700 | map_write(map, CMD(0x70), adr); | ||
1701 | |||
1702 | chip->state = FL_READY; | ||
1703 | put_chip(map, chip, adr + chip->start); | ||
1704 | ret = 0; | ||
1705 | |||
1706 | out_unlock: | ||
1707 | spin_unlock(chip->mutex); | ||
1708 | return ret; | ||
1709 | } | ||
1710 | |||
1711 | static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | ||
1712 | { | ||
1713 | return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL); | ||
1714 | } | ||
1715 | |||
1716 | static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | ||
1717 | { | ||
1718 | return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL); | ||
1719 | } | ||
1720 | |||
1610 | 1721 | ||
1611 | static void cfi_amdstd_sync (struct mtd_info *mtd) | 1722 | static void cfi_amdstd_sync (struct mtd_info *mtd) |
1612 | { | 1723 | { |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 8f39d0a31438..1154dac715aa 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -111,6 +111,7 @@ | |||
111 | #define MX29LV040C 0x004F | 111 | #define MX29LV040C 0x004F |
112 | #define MX29LV160T 0x22C4 | 112 | #define MX29LV160T 0x22C4 |
113 | #define MX29LV160B 0x2249 | 113 | #define MX29LV160B 0x2249 |
114 | #define MX29F040 0x00A4 | ||
114 | #define MX29F016 0x00AD | 115 | #define MX29F016 0x00AD |
115 | #define MX29F002T 0x00B0 | 116 | #define MX29F002T 0x00B0 |
116 | #define MX29F004T 0x0045 | 117 | #define MX29F004T 0x0045 |
@@ -1172,6 +1173,19 @@ static const struct amd_flash_info jedec_table[] = { | |||
1172 | } | 1173 | } |
1173 | }, { | 1174 | }, { |
1174 | .mfr_id = MANUFACTURER_MACRONIX, | 1175 | .mfr_id = MANUFACTURER_MACRONIX, |
1176 | .dev_id = MX29F040, | ||
1177 | .name = "Macronix MX29F040", | ||
1178 | .uaddr = { | ||
1179 | [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ | ||
1180 | }, | ||
1181 | .DevSize = SIZE_512KiB, | ||
1182 | .CmdSet = P_ID_AMD_STD, | ||
1183 | .NumEraseRegions= 1, | ||
1184 | .regions = { | ||
1185 | ERASEINFO(0x10000,8), | ||
1186 | } | ||
1187 | }, { | ||
1188 | .mfr_id = MANUFACTURER_MACRONIX, | ||
1175 | .dev_id = MX29F016, | 1189 | .dev_id = MX29F016, |
1176 | .name = "Macronix MX29F016", | 1190 | .name = "Macronix MX29F016", |
1177 | .uaddr = { | 1191 | .uaddr = { |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index ede3561be870..401c6a294baa 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
19 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/mount.h> | ||
21 | 22 | ||
22 | #define VERSION "$Revision: 1.30 $" | 23 | #define VERSION "$Revision: 1.30 $" |
23 | 24 | ||
@@ -236,6 +237,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, | |||
236 | } | 237 | } |
237 | return 0; | 238 | return 0; |
238 | } | 239 | } |
240 | |||
241 | |||
239 | static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | 242 | static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, |
240 | size_t *retlen, const u_char *buf) | 243 | size_t *retlen, const u_char *buf) |
241 | { | 244 | { |
@@ -299,6 +302,19 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
299 | 302 | ||
300 | /* Get a handle on the device */ | 303 | /* Get a handle on the device */ |
301 | bdev = open_bdev_excl(devname, O_RDWR, NULL); | 304 | bdev = open_bdev_excl(devname, O_RDWR, NULL); |
305 | #ifndef MODULE | ||
306 | if (IS_ERR(bdev)) { | ||
307 | |||
308 | /* We might not have rootfs mounted at this point. Try | ||
309 | to resolve the device name by other means. */ | ||
310 | |||
311 | dev_t dev = name_to_dev_t(devname); | ||
312 | if (dev != 0) { | ||
313 | bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); | ||
314 | } | ||
315 | } | ||
316 | #endif | ||
317 | |||
302 | if (IS_ERR(bdev)) { | 318 | if (IS_ERR(bdev)) { |
303 | ERROR("error: cannot open device %s", devname); | 319 | ERROR("error: cannot open device %s", devname); |
304 | goto devinit_err; | 320 | goto devinit_err; |
@@ -393,26 +409,6 @@ static int parse_num(size_t *num, const char *token) | |||
393 | } | 409 | } |
394 | 410 | ||
395 | 411 | ||
396 | static int parse_name(char **pname, const char *token, size_t limit) | ||
397 | { | ||
398 | size_t len; | ||
399 | char *name; | ||
400 | |||
401 | len = strlen(token) + 1; | ||
402 | if (len > limit) | ||
403 | return -ENOSPC; | ||
404 | |||
405 | name = kmalloc(len, GFP_KERNEL); | ||
406 | if (!name) | ||
407 | return -ENOMEM; | ||
408 | |||
409 | strcpy(name, token); | ||
410 | |||
411 | *pname = name; | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | |||
416 | static inline void kill_final_newline(char *str) | 412 | static inline void kill_final_newline(char *str) |
417 | { | 413 | { |
418 | char *newline = strrchr(str, '\n'); | 414 | char *newline = strrchr(str, '\n'); |
@@ -426,9 +422,15 @@ static inline void kill_final_newline(char *str) | |||
426 | return 0; \ | 422 | return 0; \ |
427 | } while (0) | 423 | } while (0) |
428 | 424 | ||
429 | static int block2mtd_setup(const char *val, struct kernel_param *kp) | 425 | #ifndef MODULE |
426 | static int block2mtd_init_called = 0; | ||
427 | static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ | ||
428 | #endif | ||
429 | |||
430 | |||
431 | static int block2mtd_setup2(const char *val) | ||
430 | { | 432 | { |
431 | char buf[80+12]; /* 80 for device, 12 for erase size */ | 433 | char buf[80 + 12]; /* 80 for device, 12 for erase size */ |
432 | char *str = buf; | 434 | char *str = buf; |
433 | char *token[2]; | 435 | char *token[2]; |
434 | char *name; | 436 | char *name; |
@@ -450,13 +452,9 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) | |||
450 | if (!token[0]) | 452 | if (!token[0]) |
451 | parse_err("no argument"); | 453 | parse_err("no argument"); |
452 | 454 | ||
453 | ret = parse_name(&name, token[0], 80); | 455 | name = token[0]; |
454 | if (ret == -ENOMEM) | 456 | if (strlen(name) + 1 > 80) |
455 | parse_err("out of memory"); | 457 | parse_err("device name too long"); |
456 | if (ret == -ENOSPC) | ||
457 | parse_err("name too long"); | ||
458 | if (ret) | ||
459 | return 0; | ||
460 | 458 | ||
461 | if (token[1]) { | 459 | if (token[1]) { |
462 | ret = parse_num(&erase_size, token[1]); | 460 | ret = parse_num(&erase_size, token[1]); |
@@ -472,13 +470,48 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) | |||
472 | } | 470 | } |
473 | 471 | ||
474 | 472 | ||
473 | static int block2mtd_setup(const char *val, struct kernel_param *kp) | ||
474 | { | ||
475 | #ifdef MODULE | ||
476 | return block2mtd_setup2(val); | ||
477 | #else | ||
478 | /* If more parameters are later passed in via | ||
479 | /sys/module/block2mtd/parameters/block2mtd | ||
480 | and block2mtd_init() has already been called, | ||
481 | we can parse the argument now. */ | ||
482 | |||
483 | if (block2mtd_init_called) | ||
484 | return block2mtd_setup2(val); | ||
485 | |||
486 | /* During early boot stage, we only save the parameters | ||
487 | here. We must parse them later: if the param passed | ||
488 | from kernel boot command line, block2mtd_setup() is | ||
489 | called so early that it is not possible to resolve | ||
490 | the device (even kmalloc() fails). Deter that work to | ||
491 | block2mtd_setup2(). */ | ||
492 | |||
493 | strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); | ||
494 | |||
495 | return 0; | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | |||
475 | module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); | 500 | module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); |
476 | MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); | 501 | MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); |
477 | 502 | ||
478 | static int __init block2mtd_init(void) | 503 | static int __init block2mtd_init(void) |
479 | { | 504 | { |
505 | int ret = 0; | ||
480 | INFO("version " VERSION); | 506 | INFO("version " VERSION); |
481 | return 0; | 507 | |
508 | #ifndef MODULE | ||
509 | if (strlen(block2mtd_paramline)) | ||
510 | ret = block2mtd_setup2(block2mtd_paramline); | ||
511 | block2mtd_init_called = 1; | ||
512 | #endif | ||
513 | |||
514 | return ret; | ||
482 | } | 515 | } |
483 | 516 | ||
484 | 517 | ||
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 6f9bbf6fee4d..2c0149708739 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -99,10 +99,6 @@ | |||
99 | #include <asm/system.h> | 99 | #include <asm/system.h> |
100 | #include <linux/pci.h> | 100 | #include <linux/pci.h> |
101 | 101 | ||
102 | #ifndef CONFIG_PCI | ||
103 | #error Enable PCI in your kernel config | ||
104 | #endif | ||
105 | |||
106 | #include <linux/mtd/mtd.h> | 102 | #include <linux/mtd/mtd.h> |
107 | #include <linux/mtd/pmc551.h> | 103 | #include <linux/mtd/pmc551.h> |
108 | #include <linux/mtd/compatmac.h> | 104 | #include <linux/mtd/compatmac.h> |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 83d0b2a52527..64d1b6a6c920 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -13,13 +13,13 @@ config MTD_COMPLEX_MAPPINGS | |||
13 | 13 | ||
14 | config MTD_PHYSMAP | 14 | config MTD_PHYSMAP |
15 | tristate "CFI Flash device in physical memory map" | 15 | tristate "CFI Flash device in physical memory map" |
16 | depends on MTD_CFI | 16 | depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM |
17 | help | 17 | help |
18 | This provides a 'mapping' driver which allows the CFI probe and | 18 | This provides a 'mapping' driver which allows the NOR Flash and |
19 | command set driver code to communicate with flash chips which | 19 | ROM driver code to communicate with chips which are mapped |
20 | are mapped physically into the CPU's memory. You will need to | 20 | physically into the CPU's memory. You will need to configure |
21 | configure the physical address and size of the flash chips on | 21 | the physical address and size of the flash chips on your |
22 | your particular board as well as the bus width, either statically | 22 | particular board as well as the bus width, either statically |
23 | with config options or at run-time. | 23 | with config options or at run-time. |
24 | 24 | ||
25 | config MTD_PHYSMAP_START | 25 | config MTD_PHYSMAP_START |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 3db77eec0ed2..c99302ed3823 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -11,7 +11,7 @@ config MTD_NAND | |||
11 | help | 11 | help |
12 | This enables support for accessing all type of NAND flash | 12 | This enables support for accessing all type of NAND flash |
13 | devices. For further information see | 13 | devices. For further information see |
14 | <http://www.linux-mtd.infradead.org/tech/nand.html>. | 14 | <http://www.linux-mtd.infradead.org/doc/nand.html>. |
15 | 15 | ||
16 | config MTD_NAND_VERIFY_WRITE | 16 | config MTD_NAND_VERIFY_WRITE |
17 | bool "Verify NAND page writes" | 17 | bool "Verify NAND page writes" |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c8cbc00243fe..975b2ef61121 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -1204,7 +1204,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
1204 | pos = steps * (eccsize + chunk); | 1204 | pos = steps * (eccsize + chunk); |
1205 | steps = 0; | 1205 | steps = 0; |
1206 | } else | 1206 | } else |
1207 | pos = eccsize + chunk; | 1207 | pos = eccsize; |
1208 | 1208 | ||
1209 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); | 1209 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); |
1210 | for (i = 0; i < steps; i++) { | 1210 | for (i = 0; i < steps; i++) { |
@@ -1567,7 +1567,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, | |||
1567 | bytes = min_t(size_t, len, free->length); | 1567 | bytes = min_t(size_t, len, free->length); |
1568 | boffs = free->offset; | 1568 | boffs = free->offset; |
1569 | } | 1569 | } |
1570 | memcpy(chip->oob_poi + woffs, oob, bytes); | 1570 | memcpy(chip->oob_poi + boffs, oob, bytes); |
1571 | oob += bytes; | 1571 | oob += bytes; |
1572 | } | 1572 | } |
1573 | return oob; | 1573 | return oob; |
@@ -2224,7 +2224,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2224 | } | 2224 | } |
2225 | 2225 | ||
2226 | /* Try to identify manufacturer */ | 2226 | /* Try to identify manufacturer */ |
2227 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) { | 2227 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { |
2228 | if (nand_manuf_ids[maf_idx].id == *maf_id) | 2228 | if (nand_manuf_ids[maf_idx].id == *maf_id) |
2229 | break; | 2229 | break; |
2230 | } | 2230 | } |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index fbeedc3184e9..51c7288ab49a 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -78,7 +78,7 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = { | |||
78 | /* | 78 | /* |
79 | * hardware specific access to control-lines | 79 | * hardware specific access to control-lines |
80 | * ctrl: | 80 | * ctrl: |
81 | * NAND_CNE: bit 0 -> bit 0 & 4 | 81 | * NAND_CNE: bit 0 -> ! bit 0 & 4 |
82 | * NAND_CLE: bit 1 -> bit 1 | 82 | * NAND_CLE: bit 1 -> bit 1 |
83 | * NAND_ALE: bit 2 -> bit 2 | 83 | * NAND_ALE: bit 2 -> bit 2 |
84 | * | 84 | * |
@@ -92,7 +92,10 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
92 | unsigned char bits = ctrl & 0x07; | 92 | unsigned char bits = ctrl & 0x07; |
93 | 93 | ||
94 | bits |= (ctrl & 0x01) << 4; | 94 | bits |= (ctrl & 0x01) << 4; |
95 | writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL); | 95 | |
96 | bits ^= 0x11; | ||
97 | |||
98 | writeb((readb(FLASHCTL) & ~0x17) | bits, FLASHCTL); | ||
96 | } | 99 | } |
97 | 100 | ||
98 | if (cmd != NAND_CMD_NONE) | 101 | if (cmd != NAND_CMD_NONE) |
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 7675b33396c7..5a6b4d64206c 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
22 | #include "nodelist.h" | 22 | #include "nodelist.h" |
23 | 23 | ||
24 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, | ||
25 | struct jffs2_node_frag *this); | ||
26 | |||
24 | void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) | 27 | void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) |
25 | { | 28 | { |
26 | struct jffs2_full_dirent **prev = list; | 29 | struct jffs2_full_dirent **prev = list; |
@@ -87,7 +90,8 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint | |||
87 | } | 90 | } |
88 | } | 91 | } |
89 | 92 | ||
90 | void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) | 93 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, |
94 | struct jffs2_node_frag *this) | ||
91 | { | 95 | { |
92 | if (this->node) { | 96 | if (this->node) { |
93 | this->node->frags--; | 97 | this->node->frags--; |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index cae92c14116d..0ddfd70307fb 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -334,7 +334,6 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); | |||
334 | struct rb_node *rb_next(struct rb_node *); | 334 | struct rb_node *rb_next(struct rb_node *); |
335 | struct rb_node *rb_prev(struct rb_node *); | 335 | struct rb_node *rb_prev(struct rb_node *); |
336 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); | 336 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); |
337 | void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); | ||
338 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); | 337 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); |
339 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); | 338 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); |
340 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); | 339 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 25bc1ae08648..4da09ce1d1f5 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -1215,7 +1215,6 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt | |||
1215 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); | 1215 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); |
1216 | if (rc) { | 1216 | if (rc) { |
1217 | JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); | 1217 | JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); |
1218 | rc = rc ? rc : -EBADFD; | ||
1219 | goto out; | 1218 | goto out; |
1220 | } | 1219 | } |
1221 | rc = save_xattr_datum(c, xd); | 1220 | rc = save_xattr_datum(c, xd); |
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 09bfae6938b3..123948b14547 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -199,6 +199,18 @@ struct cfi_pri_amdstd { | |||
199 | uint8_t TopBottom; | 199 | uint8_t TopBottom; |
200 | } __attribute__((packed)); | 200 | } __attribute__((packed)); |
201 | 201 | ||
202 | /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ | ||
203 | |||
204 | struct cfi_pri_atmel { | ||
205 | uint8_t pri[3]; | ||
206 | uint8_t MajorVersion; | ||
207 | uint8_t MinorVersion; | ||
208 | uint8_t Features; | ||
209 | uint8_t BottomBoot; | ||
210 | uint8_t BurstMode; | ||
211 | uint8_t PageMode; | ||
212 | } __attribute__((packed)); | ||
213 | |||
202 | struct cfi_pri_query { | 214 | struct cfi_pri_query { |
203 | uint8_t NumFields; | 215 | uint8_t NumFields; |
204 | uint32_t ProtField[1]; /* Not host ordered */ | 216 | uint32_t ProtField[1]; /* Not host ordered */ |
@@ -464,6 +476,7 @@ struct cfi_fixup { | |||
464 | #define CFI_ID_ANY 0xffff | 476 | #define CFI_ID_ANY 0xffff |
465 | 477 | ||
466 | #define CFI_MFR_AMD 0x0001 | 478 | #define CFI_MFR_AMD 0x0001 |
479 | #define CFI_MFR_ATMEL 0x001F | ||
467 | #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ | 480 | #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ |
468 | 481 | ||
469 | void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups); | 482 | void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups); |