aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/Kconfig8
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c87
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c112
-rw-r--r--drivers/mtd/chips/jedec_probe.c14
-rw-r--r--drivers/mtd/devices/block2mtd.c93
-rw-r--r--drivers/mtd/devices/m25p80.c12
-rw-r--r--drivers/mtd/devices/pmc551.c1158
-rw-r--r--drivers/mtd/maps/Kconfig20
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/amd76xrom.c5
-rw-r--r--drivers/mtd/maps/arctic-mtd.c14
-rw-r--r--drivers/mtd/maps/beech-mtd.c14
-rw-r--r--drivers/mtd/maps/cstm_mips_ixx.c18
-rw-r--r--drivers/mtd/maps/ebony.c4
-rw-r--r--drivers/mtd/maps/fortunet.c3
-rw-r--r--drivers/mtd/maps/ichxrom.c3
-rw-r--r--drivers/mtd/maps/iq80310.c118
-rw-r--r--drivers/mtd/maps/ixp4xx.c2
-rw-r--r--drivers/mtd/maps/l440gx.c12
-rw-r--r--drivers/mtd/maps/lasat.c2
-rw-r--r--drivers/mtd/maps/nettel.c34
-rw-r--r--drivers/mtd/maps/ocotea.c4
-rw-r--r--drivers/mtd/maps/pcmciamtd.c4
-rw-r--r--drivers/mtd/maps/physmap.c33
-rw-r--r--drivers/mtd/maps/redwood.c11
-rw-r--r--drivers/mtd/maps/sbc8240.c11
-rw-r--r--drivers/mtd/maps/scx200_docflash.c9
-rw-r--r--drivers/mtd/maps/walnut.c4
-rw-r--r--drivers/mtd/mtdchar.c9
-rw-r--r--drivers/mtd/mtdcore.c10
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/au1550nd.c11
-rw-r--r--drivers/mtd/nand/edb7312.c3
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--drivers/mtd/nand/ndfc.c2
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c7
-rw-r--r--drivers/mtd/nand/sharpsl.c7
-rw-r--r--drivers/mtd/ssfdc.c468
39 files changed, 1509 insertions, 823 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 1344ad7a4b14..717e90448fc6 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -263,6 +263,14 @@ config RFD_FTL
263 263
264 http://www.gensw.com/pages/prod/bios/rfd.htm 264 http://www.gensw.com/pages/prod/bios/rfd.htm
265 265
266config SSFDC
267 bool "NAND SSFDC (SmartMedia) read only translation layer"
268 depends on MTD
269 default n
270 help
271 This enables read only access to SmartMedia formatted NAND
272 flash. You can mount it with FAT file system.
273
266source "drivers/mtd/chips/Kconfig" 274source "drivers/mtd/chips/Kconfig"
267 275
268source "drivers/mtd/maps/Kconfig" 276source "drivers/mtd/maps/Kconfig"
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index fc9374407c2b..1e36b9aed98b 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o
21obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o 21obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o
22obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o 22obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o
23obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o 23obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o
24obj-$(CONFIG_SSFDC) += ssfdc.o mtd_blkdevs.o
24 25
25nftl-objs := nftlcore.o nftlmount.o 26nftl-objs := nftlcore.o nftlmount.o
26inftl-objs := inftlcore.o inftlmount.o 27inftl-objs := inftlcore.o inftlmount.o
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
909static int __xipram xip_wait_for_operation( 909static 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(
1040static int inval_cache_and_wait_for_operation( 1040static 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
1114static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) 1113static 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..702ae4cd8691 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
52static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); 54static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
53static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 55static 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
68static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); 70static 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
73static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
74static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
75
71static struct mtd_chip_driver cfi_amdstd_chipdrv = { 76static 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 */
170static 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((char *)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
164static void fixup_use_secsi(struct mtd_info *mtd, void *param) 189static 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,17 @@ 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 */
211static 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 mtd->flags |= MTD_STUPID_LOCK;
216}
217
182static struct cfi_fixup cfi_fixup_table[] = { 218static struct cfi_fixup cfi_fixup_table[] = {
183#ifdef AMD_BOOTLOC_BUG 219#ifdef AMD_BOOTLOC_BUG
184 { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, 220 { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
@@ -192,6 +228,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
192#if !FORCE_WORD_WRITE 228#if !FORCE_WORD_WRITE
193 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, 229 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
194#endif 230#endif
231 { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
195 { 0, 0, NULL, NULL } 232 { 0, 0, NULL, NULL }
196}; 233};
197static struct cfi_fixup jedec_fixup_table[] = { 234static struct cfi_fixup jedec_fixup_table[] = {
@@ -207,6 +244,7 @@ static struct cfi_fixup fixup_table[] = {
207 * we know that is the case. 244 * we know that is the case.
208 */ 245 */
209 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, 246 { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
247 { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
210 { 0, 0, NULL, NULL } 248 { 0, 0, NULL, NULL }
211}; 249};
212 250
@@ -1607,6 +1645,80 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
1607 return 0; 1645 return 0;
1608} 1646}
1609 1647
1648static int do_atmel_lock(struct map_info *map, struct flchip *chip,
1649 unsigned long adr, int len, void *thunk)
1650{
1651 struct cfi_private *cfi = map->fldrv_priv;
1652 int ret;
1653
1654 spin_lock(chip->mutex);
1655 ret = get_chip(map, chip, adr + chip->start, FL_LOCKING);
1656 if (ret)
1657 goto out_unlock;
1658 chip->state = FL_LOCKING;
1659
1660 DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
1661 __func__, adr, len);
1662
1663 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1664 cfi->device_type, NULL);
1665 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
1666 cfi->device_type, NULL);
1667 cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi,
1668 cfi->device_type, NULL);
1669 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1670 cfi->device_type, NULL);
1671 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
1672 cfi->device_type, NULL);
1673 map_write(map, CMD(0x40), chip->start + adr);
1674
1675 chip->state = FL_READY;
1676 put_chip(map, chip, adr + chip->start);
1677 ret = 0;
1678
1679out_unlock:
1680 spin_unlock(chip->mutex);
1681 return ret;
1682}
1683
1684static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
1685 unsigned long adr, int len, void *thunk)
1686{
1687 struct cfi_private *cfi = map->fldrv_priv;
1688 int ret;
1689
1690 spin_lock(chip->mutex);
1691 ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING);
1692 if (ret)
1693 goto out_unlock;
1694 chip->state = FL_UNLOCKING;
1695
1696 DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
1697 __func__, adr, len);
1698
1699 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
1700 cfi->device_type, NULL);
1701 map_write(map, CMD(0x70), adr);
1702
1703 chip->state = FL_READY;
1704 put_chip(map, chip, adr + chip->start);
1705 ret = 0;
1706
1707out_unlock:
1708 spin_unlock(chip->mutex);
1709 return ret;
1710}
1711
1712static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
1713{
1714 return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL);
1715}
1716
1717static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1718{
1719 return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
1720}
1721
1610 1722
1611static void cfi_amdstd_sync (struct mtd_info *mtd) 1723static void cfi_amdstd_sync (struct mtd_info *mtd)
1612{ 1724{
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
239static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, 242static 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
396static 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
416static inline void kill_final_newline(char *str) 412static 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
429static int block2mtd_setup(const char *val, struct kernel_param *kp) 425#ifndef MODULE
426static int block2mtd_init_called = 0;
427static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
428#endif
429
430
431static 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
473static 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
475module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); 500module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
476MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); 501MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
477 502
478static int __init block2mtd_init(void) 503static 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/m25p80.c b/drivers/mtd/devices/m25p80.c
index a8466141e914..ef4a731ca5c2 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -406,13 +406,13 @@ struct flash_info {
406 406
407static struct flash_info __devinitdata m25p_data [] = { 407static struct flash_info __devinitdata m25p_data [] = {
408 /* REVISIT: fill in JEDEC ids, for parts that have them */ 408 /* REVISIT: fill in JEDEC ids, for parts that have them */
409 { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, 409 { "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
410 { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, 410 { "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
411 { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, 411 { "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
412 { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, 412 { "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
413 { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, 413 { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
414 { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, 414 { "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
415 { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, 415 { "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
416 { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, 416 { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
417}; 417};
418 418
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 6f9bbf6fee4d..354e1657cc26 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -4,82 +4,82 @@
4 * PMC551 PCI Mezzanine Ram Device 4 * PMC551 PCI Mezzanine Ram Device
5 * 5 *
6 * Author: 6 * Author:
7 * Mark Ferrell <mferrell@mvista.com> 7 * Mark Ferrell <mferrell@mvista.com>
8 * Copyright 1999,2000 Nortel Networks 8 * Copyright 1999,2000 Nortel Networks
9 * 9 *
10 * License: 10 * License:
11 * As part of this driver was derived from the slram.c driver it 11 * As part of this driver was derived from the slram.c driver it
12 * falls under the same license, which is GNU General Public 12 * falls under the same license, which is GNU General Public
13 * License v2 13 * License v2
14 * 14 *
15 * Description: 15 * Description:
16 * This driver is intended to support the PMC551 PCI Ram device 16 * This driver is intended to support the PMC551 PCI Ram device
17 * from Ramix Inc. The PMC551 is a PMC Mezzanine module for 17 * from Ramix Inc. The PMC551 is a PMC Mezzanine module for
18 * cPCI embedded systems. The device contains a single SROM 18 * cPCI embedded systems. The device contains a single SROM
19 * that initially programs the V370PDC chipset onboard the 19 * that initially programs the V370PDC chipset onboard the
20 * device, and various banks of DRAM/SDRAM onboard. This driver 20 * device, and various banks of DRAM/SDRAM onboard. This driver
21 * implements this PCI Ram device as an MTD (Memory Technology 21 * implements this PCI Ram device as an MTD (Memory Technology
22 * Device) so that it can be used to hold a file system, or for 22 * Device) so that it can be used to hold a file system, or for
23 * added swap space in embedded systems. Since the memory on 23 * added swap space in embedded systems. Since the memory on
24 * this board isn't as fast as main memory we do not try to hook 24 * this board isn't as fast as main memory we do not try to hook
25 * it into main memory as that would simply reduce performance 25 * it into main memory as that would simply reduce performance
26 * on the system. Using it as a block device allows us to use 26 * on the system. Using it as a block device allows us to use
27 * it as high speed swap or for a high speed disk device of some 27 * it as high speed swap or for a high speed disk device of some
28 * sort. Which becomes very useful on diskless systems in the 28 * sort. Which becomes very useful on diskless systems in the
29 * embedded market I might add. 29 * embedded market I might add.
30 * 30 *
31 * Notes: 31 * Notes:
32 * Due to what I assume is more buggy SROM, the 64M PMC551 I 32 * Due to what I assume is more buggy SROM, the 64M PMC551 I
33 * have available claims that all 4 of it's DRAM banks have 64M 33 * have available claims that all 4 of it's DRAM banks have 64M
34 * of ram configured (making a grand total of 256M onboard). 34 * of ram configured (making a grand total of 256M onboard).
35 * This is slightly annoying since the BAR0 size reflects the 35 * This is slightly annoying since the BAR0 size reflects the
36 * aperture size, not the dram size, and the V370PDC supplies no 36 * aperture size, not the dram size, and the V370PDC supplies no
37 * other method for memory size discovery. This problem is 37 * other method for memory size discovery. This problem is
38 * mostly only relevant when compiled as a module, as the 38 * mostly only relevant when compiled as a module, as the
39 * unloading of the module with an aperture size smaller then 39 * unloading of the module with an aperture size smaller then
40 * the ram will cause the driver to detect the onboard memory 40 * the ram will cause the driver to detect the onboard memory
41 * size to be equal to the aperture size when the module is 41 * size to be equal to the aperture size when the module is
42 * reloaded. Soooo, to help, the module supports an msize 42 * reloaded. Soooo, to help, the module supports an msize
43 * option to allow the specification of the onboard memory, and 43 * option to allow the specification of the onboard memory, and
44 * an asize option, to allow the specification of the aperture 44 * an asize option, to allow the specification of the aperture
45 * size. The aperture must be equal to or less then the memory 45 * size. The aperture must be equal to or less then the memory
46 * size, the driver will correct this if you screw it up. This 46 * size, the driver will correct this if you screw it up. This
47 * problem is not relevant for compiled in drivers as compiled 47 * problem is not relevant for compiled in drivers as compiled
48 * in drivers only init once. 48 * in drivers only init once.
49 * 49 *
50 * Credits: 50 * Credits:
51 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the 51 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
52 * initial example code of how to initialize this device and for 52 * initial example code of how to initialize this device and for
53 * help with questions I had concerning operation of the device. 53 * help with questions I had concerning operation of the device.
54 * 54 *
55 * Most of the MTD code for this driver was originally written 55 * Most of the MTD code for this driver was originally written
56 * for the slram.o module in the MTD drivers package which 56 * for the slram.o module in the MTD drivers package which
57 * allows the mapping of system memory into an MTD device. 57 * allows the mapping of system memory into an MTD device.
58 * Since the PMC551 memory module is accessed in the same 58 * Since the PMC551 memory module is accessed in the same
59 * fashion as system memory, the slram.c code became a very nice 59 * fashion as system memory, the slram.c code became a very nice
60 * fit to the needs of this driver. All we added was PCI 60 * fit to the needs of this driver. All we added was PCI
61 * detection/initialization to the driver and automatically figure 61 * detection/initialization to the driver and automatically figure
62 * out the size via the PCI detection.o, later changes by Corey 62 * out the size via the PCI detection.o, later changes by Corey
63 * Minyard set up the card to utilize a 1M sliding apature. 63 * Minyard set up the card to utilize a 1M sliding apature.
64 * 64 *
65 * Corey Minyard <minyard@nortelnetworks.com> 65 * Corey Minyard <minyard@nortelnetworks.com>
66 * * Modified driver to utilize a sliding aperture instead of 66 * * Modified driver to utilize a sliding aperture instead of
67 * mapping all memory into kernel space which turned out to 67 * mapping all memory into kernel space which turned out to
68 * be very wasteful. 68 * be very wasteful.
69 * * Located a bug in the SROM's initialization sequence that 69 * * Located a bug in the SROM's initialization sequence that
70 * made the memory unusable, added a fix to code to touch up 70 * made the memory unusable, added a fix to code to touch up
71 * the DRAM some. 71 * the DRAM some.
72 * 72 *
73 * Bugs/FIXME's: 73 * Bugs/FIXME's:
74 * * MUST fix the init function to not spin on a register 74 * * MUST fix the init function to not spin on a register
75 * waiting for it to set .. this does not safely handle busted 75 * waiting for it to set .. this does not safely handle busted
76 * devices that never reset the register correctly which will 76 * devices that never reset the register correctly which will
77 * cause the system to hang w/ a reboot being the only chance at 77 * cause the system to hang w/ a reboot being the only chance at
78 * recover. [sort of fixed, could be better] 78 * recover. [sort of fixed, could be better]
79 * * Add I2C handling of the SROM so we can read the SROM's information 79 * * Add I2C handling of the SROM so we can read the SROM's information
80 * about the aperture size. This should always accurately reflect the 80 * about the aperture size. This should always accurately reflect the
81 * onboard memory size. 81 * onboard memory size.
82 * * Comb the init routine. It's still a bit cludgy on a few things. 82 * * Comb the init routine. It's still a bit cludgy on a few things.
83 */ 83 */
84 84
85#include <linux/kernel.h> 85#include <linux/kernel.h>
@@ -99,84 +99,83 @@
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>
109 105
110static struct mtd_info *pmc551list; 106static struct mtd_info *pmc551list;
111 107
112static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) 108static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
113{ 109{
114 struct mypriv *priv = mtd->priv; 110 struct mypriv *priv = mtd->priv;
115 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 111 u32 soff_hi, soff_lo; /* start address offset hi/lo */
116 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 112 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
117 unsigned long end; 113 unsigned long end;
118 u_char *ptr; 114 u_char *ptr;
119 size_t retlen; 115 size_t retlen;
120 116
121#ifdef CONFIG_MTD_PMC551_DEBUG 117#ifdef CONFIG_MTD_PMC551_DEBUG
122 printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len); 118 printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
119 (long)instr->len);
123#endif 120#endif
124 121
125 end = instr->addr + instr->len - 1; 122 end = instr->addr + instr->len - 1;
126 123
127 /* Is it past the end? */ 124 /* Is it past the end? */
128 if ( end > mtd->size ) { 125 if (end > mtd->size) {
129#ifdef CONFIG_MTD_PMC551_DEBUG 126#ifdef CONFIG_MTD_PMC551_DEBUG
130 printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", (long)end, (long)mtd->size); 127 printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n",
128 (long)end, (long)mtd->size);
131#endif 129#endif
132 return -EINVAL; 130 return -EINVAL;
133 } 131 }
134 132
135 eoff_hi = end & ~(priv->asize - 1); 133 eoff_hi = end & ~(priv->asize - 1);
136 soff_hi = instr->addr & ~(priv->asize - 1); 134 soff_hi = instr->addr & ~(priv->asize - 1);
137 eoff_lo = end & (priv->asize - 1); 135 eoff_lo = end & (priv->asize - 1);
138 soff_lo = instr->addr & (priv->asize - 1); 136 soff_lo = instr->addr & (priv->asize - 1);
139 137
140 pmc551_point (mtd, instr->addr, instr->len, &retlen, &ptr); 138 pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr);
141 139
142 if ( soff_hi == eoff_hi || mtd->size == priv->asize) { 140 if (soff_hi == eoff_hi || mtd->size == priv->asize) {
143 /* The whole thing fits within one access, so just one shot 141 /* The whole thing fits within one access, so just one shot
144 will do it. */ 142 will do it. */
145 memset(ptr, 0xff, instr->len); 143 memset(ptr, 0xff, instr->len);
146 } else { 144 } else {
147 /* We have to do multiple writes to get all the data 145 /* We have to do multiple writes to get all the data
148 written. */ 146 written. */
149 while (soff_hi != eoff_hi) { 147 while (soff_hi != eoff_hi) {
150#ifdef CONFIG_MTD_PMC551_DEBUG 148#ifdef CONFIG_MTD_PMC551_DEBUG
151 printk( KERN_DEBUG "pmc551_erase() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 149 printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
150 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
152#endif 151#endif
153 memset(ptr, 0xff, priv->asize); 152 memset(ptr, 0xff, priv->asize);
154 if (soff_hi + priv->asize >= mtd->size) { 153 if (soff_hi + priv->asize >= mtd->size) {
155 goto out; 154 goto out;
156 } 155 }
157 soff_hi += priv->asize; 156 soff_hi += priv->asize;
158 pmc551_point (mtd,(priv->base_map0|soff_hi), 157 pmc551_point(mtd, (priv->base_map0 | soff_hi),
159 priv->asize, &retlen, &ptr); 158 priv->asize, &retlen, &ptr);
160 } 159 }
161 memset (ptr, 0xff, eoff_lo); 160 memset(ptr, 0xff, eoff_lo);
162 } 161 }
163 162
164out: 163 out:
165 instr->state = MTD_ERASE_DONE; 164 instr->state = MTD_ERASE_DONE;
166#ifdef CONFIG_MTD_PMC551_DEBUG 165#ifdef CONFIG_MTD_PMC551_DEBUG
167 printk(KERN_DEBUG "pmc551_erase() done\n"); 166 printk(KERN_DEBUG "pmc551_erase() done\n");
168#endif 167#endif
169 168
170 mtd_erase_callback(instr); 169 mtd_erase_callback(instr);
171 return 0; 170 return 0;
172} 171}
173 172
174 173static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
175static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) 174 size_t * retlen, u_char ** mtdbuf)
176{ 175{
177 struct mypriv *priv = mtd->priv; 176 struct mypriv *priv = mtd->priv;
178 u32 soff_hi; 177 u32 soff_hi;
179 u32 soff_lo; 178 u32 soff_lo;
180 179
181#ifdef CONFIG_MTD_PMC551_DEBUG 180#ifdef CONFIG_MTD_PMC551_DEBUG
182 printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len); 181 printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
@@ -184,18 +183,19 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *
184 183
185 if (from + len > mtd->size) { 184 if (from + len > mtd->size) {
186#ifdef CONFIG_MTD_PMC551_DEBUG 185#ifdef CONFIG_MTD_PMC551_DEBUG
187 printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", (long)from+len, (long)mtd->size); 186 printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n",
187 (long)from + len, (long)mtd->size);
188#endif 188#endif
189 return -EINVAL; 189 return -EINVAL;
190 } 190 }
191 191
192 soff_hi = from & ~(priv->asize - 1); 192 soff_hi = from & ~(priv->asize - 1);
193 soff_lo = from & (priv->asize - 1); 193 soff_lo = from & (priv->asize - 1);
194 194
195 /* Cheap hack optimization */ 195 /* Cheap hack optimization */
196 if( priv->curr_map0 != from ) { 196 if (priv->curr_map0 != from) {
197 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, 197 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
198 (priv->base_map0 | soff_hi) ); 198 (priv->base_map0 | soff_hi));
199 priv->curr_map0 = soff_hi; 199 priv->curr_map0 = soff_hi;
200 } 200 }
201 201
@@ -204,137 +204,144 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *
204 return 0; 204 return 0;
205} 205}
206 206
207 207static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
208static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 208 size_t len)
209{ 209{
210#ifdef CONFIG_MTD_PMC551_DEBUG 210#ifdef CONFIG_MTD_PMC551_DEBUG
211 printk(KERN_DEBUG "pmc551_unpoint()\n"); 211 printk(KERN_DEBUG "pmc551_unpoint()\n");
212#endif 212#endif
213} 213}
214 214
215 215static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
216static int pmc551_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) 216 size_t * retlen, u_char * buf)
217{ 217{
218 struct mypriv *priv = mtd->priv; 218 struct mypriv *priv = mtd->priv;
219 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 219 u32 soff_hi, soff_lo; /* start address offset hi/lo */
220 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 220 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
221 unsigned long end; 221 unsigned long end;
222 u_char *ptr; 222 u_char *ptr;
223 u_char *copyto = buf; 223 u_char *copyto = buf;
224 224
225#ifdef CONFIG_MTD_PMC551_DEBUG 225#ifdef CONFIG_MTD_PMC551_DEBUG
226 printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", (long)from, (long)len, (long)priv->asize); 226 printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
227 (long)from, (long)len, (long)priv->asize);
227#endif 228#endif
228 229
229 end = from + len - 1; 230 end = from + len - 1;
230 231
231 /* Is it past the end? */ 232 /* Is it past the end? */
232 if (end > mtd->size) { 233 if (end > mtd->size) {
233#ifdef CONFIG_MTD_PMC551_DEBUG 234#ifdef CONFIG_MTD_PMC551_DEBUG
234 printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", (long) end, (long)mtd->size); 235 printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n",
236 (long)end, (long)mtd->size);
235#endif 237#endif
236 return -EINVAL; 238 return -EINVAL;
237 } 239 }
238 240
239 soff_hi = from & ~(priv->asize - 1); 241 soff_hi = from & ~(priv->asize - 1);
240 eoff_hi = end & ~(priv->asize - 1); 242 eoff_hi = end & ~(priv->asize - 1);
241 soff_lo = from & (priv->asize - 1); 243 soff_lo = from & (priv->asize - 1);
242 eoff_lo = end & (priv->asize - 1); 244 eoff_lo = end & (priv->asize - 1);
243 245
244 pmc551_point (mtd, from, len, retlen, &ptr); 246 pmc551_point(mtd, from, len, retlen, &ptr);
245 247
246 if (soff_hi == eoff_hi) { 248 if (soff_hi == eoff_hi) {
247 /* The whole thing fits within one access, so just one shot 249 /* The whole thing fits within one access, so just one shot
248 will do it. */ 250 will do it. */
249 memcpy(copyto, ptr, len); 251 memcpy(copyto, ptr, len);
250 copyto += len; 252 copyto += len;
251 } else { 253 } else {
252 /* We have to do multiple writes to get all the data 254 /* We have to do multiple writes to get all the data
253 written. */ 255 written. */
254 while (soff_hi != eoff_hi) { 256 while (soff_hi != eoff_hi) {
255#ifdef CONFIG_MTD_PMC551_DEBUG 257#ifdef CONFIG_MTD_PMC551_DEBUG
256 printk( KERN_DEBUG "pmc551_read() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 258 printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
259 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
257#endif 260#endif
258 memcpy(copyto, ptr, priv->asize); 261 memcpy(copyto, ptr, priv->asize);
259 copyto += priv->asize; 262 copyto += priv->asize;
260 if (soff_hi + priv->asize >= mtd->size) { 263 if (soff_hi + priv->asize >= mtd->size) {
261 goto out; 264 goto out;
262 } 265 }
263 soff_hi += priv->asize; 266 soff_hi += priv->asize;
264 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); 267 pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
265 } 268 }
266 memcpy(copyto, ptr, eoff_lo); 269 memcpy(copyto, ptr, eoff_lo);
267 copyto += eoff_lo; 270 copyto += eoff_lo;
268 } 271 }
269 272
270out: 273 out:
271#ifdef CONFIG_MTD_PMC551_DEBUG 274#ifdef CONFIG_MTD_PMC551_DEBUG
272 printk(KERN_DEBUG "pmc551_read() done\n"); 275 printk(KERN_DEBUG "pmc551_read() done\n");
273#endif 276#endif
274 *retlen = copyto - buf; 277 *retlen = copyto - buf;
275 return 0; 278 return 0;
276} 279}
277 280
278static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) 281static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
282 size_t * retlen, const u_char * buf)
279{ 283{
280 struct mypriv *priv = mtd->priv; 284 struct mypriv *priv = mtd->priv;
281 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 285 u32 soff_hi, soff_lo; /* start address offset hi/lo */
282 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 286 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
283 unsigned long end; 287 unsigned long end;
284 u_char *ptr; 288 u_char *ptr;
285 const u_char *copyfrom = buf; 289 const u_char *copyfrom = buf;
286
287 290
288#ifdef CONFIG_MTD_PMC551_DEBUG 291#ifdef CONFIG_MTD_PMC551_DEBUG
289 printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", (long)to, (long)len, (long)priv->asize); 292 printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
293 (long)to, (long)len, (long)priv->asize);
290#endif 294#endif
291 295
292 end = to + len - 1; 296 end = to + len - 1;
293 /* Is it past the end? or did the u32 wrap? */ 297 /* Is it past the end? or did the u32 wrap? */
294 if (end > mtd->size ) { 298 if (end > mtd->size) {
295#ifdef CONFIG_MTD_PMC551_DEBUG 299#ifdef CONFIG_MTD_PMC551_DEBUG
296 printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, size: %ld, to: %ld)\n", (long) end, (long)mtd->size, (long)to); 300 printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, "
301 "size: %ld, to: %ld)\n", (long)end, (long)mtd->size,
302 (long)to);
297#endif 303#endif
298 return -EINVAL; 304 return -EINVAL;
299 } 305 }
300 306
301 soff_hi = to & ~(priv->asize - 1); 307 soff_hi = to & ~(priv->asize - 1);
302 eoff_hi = end & ~(priv->asize - 1); 308 eoff_hi = end & ~(priv->asize - 1);
303 soff_lo = to & (priv->asize - 1); 309 soff_lo = to & (priv->asize - 1);
304 eoff_lo = end & (priv->asize - 1); 310 eoff_lo = end & (priv->asize - 1);
305 311
306 pmc551_point (mtd, to, len, retlen, &ptr); 312 pmc551_point(mtd, to, len, retlen, &ptr);
307 313
308 if (soff_hi == eoff_hi) { 314 if (soff_hi == eoff_hi) {
309 /* The whole thing fits within one access, so just one shot 315 /* The whole thing fits within one access, so just one shot
310 will do it. */ 316 will do it. */
311 memcpy(ptr, copyfrom, len); 317 memcpy(ptr, copyfrom, len);
312 copyfrom += len; 318 copyfrom += len;
313 } else { 319 } else {
314 /* We have to do multiple writes to get all the data 320 /* We have to do multiple writes to get all the data
315 written. */ 321 written. */
316 while (soff_hi != eoff_hi) { 322 while (soff_hi != eoff_hi) {
317#ifdef CONFIG_MTD_PMC551_DEBUG 323#ifdef CONFIG_MTD_PMC551_DEBUG
318 printk( KERN_DEBUG "pmc551_write() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 324 printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
325 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
319#endif 326#endif
320 memcpy(ptr, copyfrom, priv->asize); 327 memcpy(ptr, copyfrom, priv->asize);
321 copyfrom += priv->asize; 328 copyfrom += priv->asize;
322 if (soff_hi >= mtd->size) { 329 if (soff_hi >= mtd->size) {
323 goto out; 330 goto out;
324 } 331 }
325 soff_hi += priv->asize; 332 soff_hi += priv->asize;
326 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); 333 pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
327 } 334 }
328 memcpy(ptr, copyfrom, eoff_lo); 335 memcpy(ptr, copyfrom, eoff_lo);
329 copyfrom += eoff_lo; 336 copyfrom += eoff_lo;
330 } 337 }
331 338
332out: 339 out:
333#ifdef CONFIG_MTD_PMC551_DEBUG 340#ifdef CONFIG_MTD_PMC551_DEBUG
334 printk(KERN_DEBUG "pmc551_write() done\n"); 341 printk(KERN_DEBUG "pmc551_write() done\n");
335#endif 342#endif
336 *retlen = copyfrom - buf; 343 *retlen = copyfrom - buf;
337 return 0; 344 return 0;
338} 345}
339 346
340/* 347/*
@@ -349,58 +356,58 @@ out:
349 * mechanism 356 * mechanism
350 * returns the size of the memory region found. 357 * returns the size of the memory region found.
351 */ 358 */
352static u32 fixup_pmc551 (struct pci_dev *dev) 359static u32 fixup_pmc551(struct pci_dev *dev)
353{ 360{
354#ifdef CONFIG_MTD_PMC551_BUGFIX 361#ifdef CONFIG_MTD_PMC551_BUGFIX
355 u32 dram_data; 362 u32 dram_data;
356#endif 363#endif
357 u32 size, dcmd, cfg, dtmp; 364 u32 size, dcmd, cfg, dtmp;
358 u16 cmd, tmp, i; 365 u16 cmd, tmp, i;
359 u8 bcmd, counter; 366 u8 bcmd, counter;
360 367
361 /* Sanity Check */ 368 /* Sanity Check */
362 if(!dev) { 369 if (!dev) {
363 return -ENODEV; 370 return -ENODEV;
364 } 371 }
365 372
366 /* 373 /*
367 * Attempt to reset the card 374 * Attempt to reset the card
368 * FIXME: Stop Spinning registers 375 * FIXME: Stop Spinning registers
369 */ 376 */
370 counter=0; 377 counter = 0;
371 /* unlock registers */ 378 /* unlock registers */
372 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); 379 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
373 /* read in old data */ 380 /* read in old data */
374 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); 381 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
375 /* bang the reset line up and down for a few */ 382 /* bang the reset line up and down for a few */
376 for(i=0;i<10;i++) { 383 for (i = 0; i < 10; i++) {
377 counter=0; 384 counter = 0;
378 bcmd &= ~0x80; 385 bcmd &= ~0x80;
379 while(counter++ < 100) { 386 while (counter++ < 100) {
380 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 387 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
381 } 388 }
382 counter=0; 389 counter = 0;
383 bcmd |= 0x80; 390 bcmd |= 0x80;
384 while(counter++ < 100) { 391 while (counter++ < 100) {
385 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 392 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
386 } 393 }
387 } 394 }
388 bcmd |= (0x40|0x20); 395 bcmd |= (0x40 | 0x20);
389 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 396 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
390 397
391 /* 398 /*
392 * Take care and turn off the memory on the device while we 399 * Take care and turn off the memory on the device while we
393 * tweak the configurations 400 * tweak the configurations
394 */ 401 */
395 pci_read_config_word(dev, PCI_COMMAND, &cmd); 402 pci_read_config_word(dev, PCI_COMMAND, &cmd);
396 tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); 403 tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
397 pci_write_config_word(dev, PCI_COMMAND, tmp); 404 pci_write_config_word(dev, PCI_COMMAND, tmp);
398 405
399 /* 406 /*
400 * Disable existing aperture before probing memory size 407 * Disable existing aperture before probing memory size
401 */ 408 */
402 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); 409 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
403 dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); 410 dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
404 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); 411 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
405 /* 412 /*
406 * Grab old BAR0 config so that we can figure out memory size 413 * Grab old BAR0 config so that we can figure out memory size
@@ -411,220 +418,230 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
411 * then write all 1's to the memory space, read back the result into 418 * then write all 1's to the memory space, read back the result into
412 * "size", and then write back all the old config. 419 * "size", and then write back all the old config.
413 */ 420 */
414 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); 421 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
415#ifndef CONFIG_MTD_PMC551_BUGFIX 422#ifndef CONFIG_MTD_PMC551_BUGFIX
416 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); 423 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
417 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); 424 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
418 size = (size&PCI_BASE_ADDRESS_MEM_MASK); 425 size = (size & PCI_BASE_ADDRESS_MEM_MASK);
419 size &= ~(size-1); 426 size &= ~(size - 1);
420 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); 427 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
421#else 428#else
422 /* 429 /*
423 * Get the size of the memory by reading all the DRAM size values 430 * Get the size of the memory by reading all the DRAM size values
424 * and adding them up. 431 * and adding them up.
425 * 432 *
426 * KLUDGE ALERT: the boards we are using have invalid column and 433 * KLUDGE ALERT: the boards we are using have invalid column and
427 * row mux values. We fix them here, but this will break other 434 * row mux values. We fix them here, but this will break other
428 * memory configurations. 435 * memory configurations.
429 */ 436 */
430 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); 437 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
431 size = PMC551_DRAM_BLK_GET_SIZE(dram_data); 438 size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
432 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 439 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
433 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 440 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
434 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); 441 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
435 442
436 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); 443 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
437 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 444 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
438 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 445 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
439 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 446 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
440 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); 447 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
441 448
442 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); 449 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
443 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 450 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
444 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 451 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
445 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 452 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
446 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); 453 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
447 454
448 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); 455 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
449 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 456 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
450 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 457 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
451 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 458 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
452 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); 459 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
453 460
454 /* 461 /*
455 * Oops .. something went wrong 462 * Oops .. something went wrong
456 */ 463 */
457 if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { 464 if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
458 return -ENODEV; 465 return -ENODEV;
459 } 466 }
460#endif /* CONFIG_MTD_PMC551_BUGFIX */ 467#endif /* CONFIG_MTD_PMC551_BUGFIX */
461 468
462 if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { 469 if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
463 return -ENODEV; 470 return -ENODEV;
464 } 471 }
465 472
466 /* 473 /*
467 * Precharge Dram 474 * Precharge Dram
468 */ 475 */
469 pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); 476 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
470 pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); 477 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
471 478
472 /* 479 /*
473 * Wait until command has gone through 480 * Wait until command has gone through
474 * FIXME: register spinning issue 481 * FIXME: register spinning issue
475 */ 482 */
476 do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); 483 do {
477 if(counter++ > 100)break; 484 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
478 } while ( (PCI_COMMAND_IO) & cmd ); 485 if (counter++ > 100)
479 486 break;
480 /* 487 } while ((PCI_COMMAND_IO) & cmd);
488
489 /*
481 * Turn on auto refresh 490 * Turn on auto refresh
482 * The loop is taken directly from Ramix's example code. I assume that 491 * The loop is taken directly from Ramix's example code. I assume that
483 * this must be held high for some duration of time, but I can find no 492 * this must be held high for some duration of time, but I can find no
484 * documentation refrencing the reasons why. 493 * documentation refrencing the reasons why.
485 */ 494 */
486 for ( i = 1; i<=8 ; i++) { 495 for (i = 1; i <= 8; i++) {
487 pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); 496 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
488 497
489 /* 498 /*
490 * Make certain command has gone through 499 * Make certain command has gone through
491 * FIXME: register spinning issue 500 * FIXME: register spinning issue
492 */ 501 */
493 counter=0; 502 counter = 0;
494 do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); 503 do {
495 if(counter++ > 100)break; 504 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
496 } while ( (PCI_COMMAND_IO) & cmd ); 505 if (counter++ > 100)
497 } 506 break;
498 507 } while ((PCI_COMMAND_IO) & cmd);
499 pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); 508 }
500 pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); 509
501 510 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
502 /* 511 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
503 * Wait until command completes 512
504 * FIXME: register spinning issue 513 /*
505 */ 514 * Wait until command completes
506 counter=0; 515 * FIXME: register spinning issue
507 do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); 516 */
508 if(counter++ > 100)break; 517 counter = 0;
509 } while ( (PCI_COMMAND_IO) & cmd ); 518 do {
510 519 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
511 pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); 520 if (counter++ > 100)
512 dcmd |= 0x02000000; 521 break;
513 pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); 522 } while ((PCI_COMMAND_IO) & cmd);
514 523
515 /* 524 pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
516 * Check to make certain fast back-to-back, if not 525 dcmd |= 0x02000000;
517 * then set it so 526 pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
518 */ 527
519 pci_read_config_word( dev, PCI_STATUS, &cmd); 528 /*
520 if((cmd&PCI_COMMAND_FAST_BACK) == 0) { 529 * Check to make certain fast back-to-back, if not
521 cmd |= PCI_COMMAND_FAST_BACK; 530 * then set it so
522 pci_write_config_word( dev, PCI_STATUS, cmd); 531 */
523 } 532 pci_read_config_word(dev, PCI_STATUS, &cmd);
524 533 if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
525 /* 534 cmd |= PCI_COMMAND_FAST_BACK;
526 * Check to make certain the DEVSEL is set correctly, this device 535 pci_write_config_word(dev, PCI_STATUS, cmd);
527 * has a tendancy to assert DEVSEL and TRDY when a write is performed 536 }
528 * to the memory when memory is read-only 537
529 */ 538 /*
530 if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { 539 * Check to make certain the DEVSEL is set correctly, this device
531 cmd &= ~PCI_STATUS_DEVSEL_MASK; 540 * has a tendancy to assert DEVSEL and TRDY when a write is performed
532 pci_write_config_word( dev, PCI_STATUS, cmd ); 541 * to the memory when memory is read-only
533 } 542 */
534 /* 543 if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
535 * Set to be prefetchable and put everything back based on old cfg. 544 cmd &= ~PCI_STATUS_DEVSEL_MASK;
545 pci_write_config_word(dev, PCI_STATUS, cmd);
546 }
547 /*
548 * Set to be prefetchable and put everything back based on old cfg.
536 * it's possible that the reset of the V370PDC nuked the original 549 * it's possible that the reset of the V370PDC nuked the original
537 * setup 550 * setup
538 */ 551 */
552 /*
553 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
554 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
555 */
556
539 /* 557 /*
540 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; 558 * Turn PCI memory and I/O bus access back on
541 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); 559 */
542 */ 560 pci_write_config_word(dev, PCI_COMMAND,
543 561 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
544 /*
545 * Turn PCI memory and I/O bus access back on
546 */
547 pci_write_config_word( dev, PCI_COMMAND,
548 PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
549#ifdef CONFIG_MTD_PMC551_DEBUG 562#ifdef CONFIG_MTD_PMC551_DEBUG
550 /* 563 /*
551 * Some screen fun 564 * Some screen fun
552 */ 565 */
553 printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%llx\n", 566 printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
554 (size<1024)?size:(size<1048576)?size>>10:size>>20, 567 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
555 (size<1024)?'B':(size<1048576)?'K':'M', 568 size >> 10 : size >> 20,
556 size, ((dcmd&(0x1<<3)) == 0)?"non-":"", 569 (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
557 (unsigned long long)((dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK)); 570 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
558 571 (unsigned long long)pci_resource_start(dev, 0));
559 /* 572
560 * Check to see the state of the memory 573 /*
561 */ 574 * Check to see the state of the memory
562 pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); 575 */
563 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" 576 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
564 "pmc551: DRAM_BLK0 Size: %d at %d\n" 577 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
565 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", 578 "pmc551: DRAM_BLK0 Size: %d at %d\n"
566 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 579 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
567 (((0x1<<0)&dcmd) == 0)?"Off":"On", 580 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
568 PMC551_DRAM_BLK_GET_SIZE(dcmd), 581 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
569 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 582 PMC551_DRAM_BLK_GET_SIZE(dcmd),
570 583 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
571 pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); 584 ((dcmd >> 9) & 0xF));
572 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" 585
573 "pmc551: DRAM_BLK1 Size: %d at %d\n" 586 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
574 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", 587 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
575 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 588 "pmc551: DRAM_BLK1 Size: %d at %d\n"
576 (((0x1<<0)&dcmd) == 0)?"Off":"On", 589 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
577 PMC551_DRAM_BLK_GET_SIZE(dcmd), 590 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
578 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 591 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
579 592 PMC551_DRAM_BLK_GET_SIZE(dcmd),
580 pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); 593 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
581 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" 594 ((dcmd >> 9) & 0xF));
582 "pmc551: DRAM_BLK2 Size: %d at %d\n" 595
583 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", 596 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
584 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 597 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
585 (((0x1<<0)&dcmd) == 0)?"Off":"On", 598 "pmc551: DRAM_BLK2 Size: %d at %d\n"
586 PMC551_DRAM_BLK_GET_SIZE(dcmd), 599 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
587 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 600 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
588 601 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
589 pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); 602 PMC551_DRAM_BLK_GET_SIZE(dcmd),
590 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" 603 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
591 "pmc551: DRAM_BLK3 Size: %d at %d\n" 604 ((dcmd >> 9) & 0xF));
592 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", 605
593 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 606 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
594 (((0x1<<0)&dcmd) == 0)?"Off":"On", 607 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
595 PMC551_DRAM_BLK_GET_SIZE(dcmd), 608 "pmc551: DRAM_BLK3 Size: %d at %d\n"
596 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 609 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
597 610 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
598 pci_read_config_word( dev, PCI_COMMAND, &cmd ); 611 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
599 printk( KERN_DEBUG "pmc551: Memory Access %s\n", 612 PMC551_DRAM_BLK_GET_SIZE(dcmd),
600 (((0x1<<1)&cmd) == 0)?"off":"on" ); 613 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
601 printk( KERN_DEBUG "pmc551: I/O Access %s\n", 614 ((dcmd >> 9) & 0xF));
602 (((0x1<<0)&cmd) == 0)?"off":"on" ); 615
603 616 pci_read_config_word(dev, PCI_COMMAND, &cmd);
604 pci_read_config_word( dev, PCI_STATUS, &cmd ); 617 printk(KERN_DEBUG "pmc551: Memory Access %s\n",
605 printk( KERN_DEBUG "pmc551: Devsel %s\n", 618 (((0x1 << 1) & cmd) == 0) ? "off" : "on");
606 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": 619 printk(KERN_DEBUG "pmc551: I/O Access %s\n",
607 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": 620 (((0x1 << 0) & cmd) == 0) ? "off" : "on");
608 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); 621
609 622 pci_read_config_word(dev, PCI_STATUS, &cmd);
610 printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", 623 printk(KERN_DEBUG "pmc551: Devsel %s\n",
611 ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); 624 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
612 625 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
613 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); 626 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
614 printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" 627
615 "pmc551: System Control Register is %slocked to PCI access\n" 628 printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
616 "pmc551: System Control Register is %slocked to EEPROM access\n", 629 ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
617 (bcmd&0x1)?"software":"hardware", 630
618 (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); 631 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
632 printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
633 "pmc551: System Control Register is %slocked to PCI access\n"
634 "pmc551: System Control Register is %slocked to EEPROM access\n",
635 (bcmd & 0x1) ? "software" : "hardware",
636 (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
619#endif 637#endif
620 return size; 638 return size;
621} 639}
622 640
623/* 641/*
624 * Kernel version specific module stuffages 642 * Kernel version specific module stuffages
625 */ 643 */
626 644
627
628MODULE_LICENSE("GPL"); 645MODULE_LICENSE("GPL");
629MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>"); 646MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
630MODULE_DESCRIPTION(PMC551_VERSION); 647MODULE_DESCRIPTION(PMC551_VERSION);
@@ -632,11 +649,11 @@ MODULE_DESCRIPTION(PMC551_VERSION);
632/* 649/*
633 * Stuff these outside the ifdef so as to not bust compiled in driver support 650 * Stuff these outside the ifdef so as to not bust compiled in driver support
634 */ 651 */
635static int msize=0; 652static int msize = 0;
636#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) 653#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
637static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE 654static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE
638#else 655#else
639static int asize=0; 656static int asize = 0;
640#endif 657#endif
641 658
642module_param(msize, int, 0); 659module_param(msize, int, 0);
@@ -649,164 +666,174 @@ MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
649 */ 666 */
650static int __init init_pmc551(void) 667static int __init init_pmc551(void)
651{ 668{
652 struct pci_dev *PCI_Device = NULL; 669 struct pci_dev *PCI_Device = NULL;
653 struct mypriv *priv; 670 struct mypriv *priv;
654 int count, found=0; 671 int count, found = 0;
655 struct mtd_info *mtd; 672 struct mtd_info *mtd;
656 u32 length = 0; 673 u32 length = 0;
657 674
658 if(msize) { 675 if (msize) {
659 msize = (1 << (ffs(msize) - 1))<<20; 676 msize = (1 << (ffs(msize) - 1)) << 20;
660 if (msize > (1<<30)) { 677 if (msize > (1 << 30)) {
661 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", msize); 678 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
679 msize);
662 return -EINVAL; 680 return -EINVAL;
663 } 681 }
664 } 682 }
665 683
666 if(asize) { 684 if (asize) {
667 asize = (1 << (ffs(asize) - 1))<<20; 685 asize = (1 << (ffs(asize) - 1)) << 20;
668 if (asize > (1<<30) ) { 686 if (asize > (1 << 30)) {
669 printk(KERN_NOTICE "pmc551: Invalid aperture size [%d]\n", asize); 687 printk(KERN_NOTICE "pmc551: Invalid aperture size "
688 "[%d]\n", asize);
670 return -EINVAL; 689 return -EINVAL;
671 } 690 }
672 } 691 }
673 692
674 printk(KERN_INFO PMC551_VERSION); 693 printk(KERN_INFO PMC551_VERSION);
675 694
676 /* 695 /*
677 * PCU-bus chipset probe. 696 * PCU-bus chipset probe.
678 */ 697 */
679 for( count = 0; count < MAX_MTD_DEVICES; count++ ) { 698 for (count = 0; count < MAX_MTD_DEVICES; count++) {
680 699
681 if ((PCI_Device = pci_find_device(PCI_VENDOR_ID_V3_SEMI, 700 if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
682 PCI_DEVICE_ID_V3_SEMI_V370PDC, 701 PCI_DEVICE_ID_V3_SEMI_V370PDC,
683 PCI_Device ) ) == NULL) { 702 PCI_Device)) == NULL) {
684 break; 703 break;
685 } 704 }
686 705
687 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", 706 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
688 (unsigned long long)PCI_Device->resource[0].start); 707 (unsigned long long)pci_resource_start(PCI_Device, 0));
689 708
690 /* 709 /*
691 * The PMC551 device acts VERY weird if you don't init it 710 * The PMC551 device acts VERY weird if you don't init it
692 * first. i.e. it will not correctly report devsel. If for 711 * first. i.e. it will not correctly report devsel. If for
693 * some reason the sdram is in a wrote-protected state the 712 * some reason the sdram is in a wrote-protected state the
694 * device will DEVSEL when it is written to causing problems 713 * device will DEVSEL when it is written to causing problems
695 * with the oldproc.c driver in 714 * with the oldproc.c driver in
696 * some kernels (2.2.*) 715 * some kernels (2.2.*)
697 */ 716 */
698 if((length = fixup_pmc551(PCI_Device)) <= 0) { 717 if ((length = fixup_pmc551(PCI_Device)) <= 0) {
699 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); 718 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
700 break; 719 break;
701 } 720 }
702 721
703 /* 722 /*
704 * This is needed until the driver is capable of reading the 723 * This is needed until the driver is capable of reading the
705 * onboard I2C SROM to discover the "real" memory size. 724 * onboard I2C SROM to discover the "real" memory size.
706 */ 725 */
707 if(msize) { 726 if (msize) {
708 length = msize; 727 length = msize;
709 printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length); 728 printk(KERN_NOTICE "pmc551: Using specified memory "
729 "size 0x%x\n", length);
710 } else { 730 } else {
711 msize = length; 731 msize = length;
712 } 732 }
713 733
714 mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 734 mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
715 if (!mtd) { 735 if (!mtd) {
716 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); 736 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
717 break; 737 "device.\n");
718 } 738 break;
719 739 }
720 memset(mtd, 0, sizeof(struct mtd_info)); 740
721 741 priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
722 priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); 742 if (!priv) {
723 if (!priv) { 743 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
724 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); 744 "device.\n");
725 kfree(mtd); 745 kfree(mtd);
726 break; 746 break;
727 } 747 }
728 memset(priv, 0, sizeof(*priv)); 748 mtd->priv = priv;
729 mtd->priv = priv; 749 priv->dev = PCI_Device;
730 priv->dev = PCI_Device; 750
731 751 if (asize > length) {
732 if(asize > length) { 752 printk(KERN_NOTICE "pmc551: reducing aperture size to "
733 printk(KERN_NOTICE "pmc551: reducing aperture size to fit %dM\n",length>>20); 753 "fit %dM\n", length >> 20);
734 priv->asize = asize = length; 754 priv->asize = asize = length;
735 } else if (asize == 0 || asize == length) { 755 } else if (asize == 0 || asize == length) {
736 printk(KERN_NOTICE "pmc551: Using existing aperture size %dM\n", length>>20); 756 printk(KERN_NOTICE "pmc551: Using existing aperture "
757 "size %dM\n", length >> 20);
737 priv->asize = asize = length; 758 priv->asize = asize = length;
738 } else { 759 } else {
739 printk(KERN_NOTICE "pmc551: Using specified aperture size %dM\n", asize>>20); 760 printk(KERN_NOTICE "pmc551: Using specified aperture "
761 "size %dM\n", asize >> 20);
740 priv->asize = asize; 762 priv->asize = asize;
741 } 763 }
742 priv->start = ioremap(((PCI_Device->resource[0].start) 764 priv->start = pci_iomap(PCI_Device, 0, priv->asize);
743 & PCI_BASE_ADDRESS_MEM_MASK),
744 priv->asize);
745 765
746 if (!priv->start) { 766 if (!priv->start) {
747 printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); 767 printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
748 kfree(mtd->priv); 768 kfree(mtd->priv);
749 kfree(mtd); 769 kfree(mtd);
750 break; 770 break;
751 } 771 }
752
753#ifdef CONFIG_MTD_PMC551_DEBUG 772#ifdef CONFIG_MTD_PMC551_DEBUG
754 printk( KERN_DEBUG "pmc551: setting aperture to %d\n", 773 printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
755 ffs(priv->asize>>20)-1); 774 ffs(priv->asize >> 20) - 1);
756#endif 775#endif
757 776
758 priv->base_map0 = ( PMC551_PCI_MEM_MAP_REG_EN 777 priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
759 | PMC551_PCI_MEM_MAP_ENABLE 778 | PMC551_PCI_MEM_MAP_ENABLE
760 | (ffs(priv->asize>>20)-1)<<4 ); 779 | (ffs(priv->asize >> 20) - 1) << 4);
761 priv->curr_map0 = priv->base_map0; 780 priv->curr_map0 = priv->base_map0;
762 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, 781 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
763 priv->curr_map0 ); 782 priv->curr_map0);
764 783
765#ifdef CONFIG_MTD_PMC551_DEBUG 784#ifdef CONFIG_MTD_PMC551_DEBUG
766 printk( KERN_DEBUG "pmc551: aperture set to %d\n", 785 printk(KERN_DEBUG "pmc551: aperture set to %d\n",
767 (priv->base_map0 & 0xF0)>>4 ); 786 (priv->base_map0 & 0xF0) >> 4);
768#endif 787#endif
769 788
770 mtd->size = msize; 789 mtd->size = msize;
771 mtd->flags = MTD_CAP_RAM; 790 mtd->flags = MTD_CAP_RAM;
772 mtd->erase = pmc551_erase; 791 mtd->erase = pmc551_erase;
773 mtd->read = pmc551_read; 792 mtd->read = pmc551_read;
774 mtd->write = pmc551_write; 793 mtd->write = pmc551_write;
775 mtd->point = pmc551_point; 794 mtd->point = pmc551_point;
776 mtd->unpoint = pmc551_unpoint; 795 mtd->unpoint = pmc551_unpoint;
777 mtd->type = MTD_RAM; 796 mtd->type = MTD_RAM;
778 mtd->name = "PMC551 RAM board"; 797 mtd->name = "PMC551 RAM board";
779 mtd->erasesize = 0x10000; 798 mtd->erasesize = 0x10000;
780 mtd->writesize = 1; 799 mtd->writesize = 1;
781 mtd->owner = THIS_MODULE; 800 mtd->owner = THIS_MODULE;
782 801
783 if (add_mtd_device(mtd)) { 802 if (add_mtd_device(mtd)) {
784 printk(KERN_NOTICE "pmc551: Failed to register new device\n"); 803 printk(KERN_NOTICE "pmc551: Failed to register new "
785 iounmap(priv->start); 804 "device\n");
786 kfree(mtd->priv); 805 pci_iounmap(PCI_Device, priv->start);
787 kfree(mtd); 806 kfree(mtd->priv);
788 break; 807 kfree(mtd);
789 } 808 break;
790 printk(KERN_NOTICE "Registered pmc551 memory device.\n"); 809 }
791 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", 810
792 priv->asize>>20, 811 /* Keep a reference as the add_mtd_device worked */
793 priv->start, 812 pci_dev_get(PCI_Device);
794 priv->start + priv->asize); 813
795 printk(KERN_NOTICE "Total memory is %d%c\n", 814 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
796 (length<1024)?length: 815 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
797 (length<1048576)?length>>10:length>>20, 816 priv->asize >> 20,
798 (length<1024)?'B':(length<1048576)?'K':'M'); 817 priv->start, priv->start + priv->asize);
818 printk(KERN_NOTICE "Total memory is %d%c\n",
819 (length < 1024) ? length :
820 (length < 1048576) ? length >> 10 : length >> 20,
821 (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
799 priv->nextpmc551 = pmc551list; 822 priv->nextpmc551 = pmc551list;
800 pmc551list = mtd; 823 pmc551list = mtd;
801 found++; 824 found++;
802 } 825 }
826
827 /* Exited early, reference left over */
828 if (PCI_Device)
829 pci_dev_put(PCI_Device);
803 830
804 if( !pmc551list ) { 831 if (!pmc551list) {
805 printk(KERN_NOTICE "pmc551: not detected\n"); 832 printk(KERN_NOTICE "pmc551: not detected\n");
806 return -ENODEV; 833 return -ENODEV;
807 } else { 834 } else {
808 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); 835 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
809 return 0; 836 return 0;
810 } 837 }
811} 838}
812 839
@@ -815,23 +842,24 @@ static int __init init_pmc551(void)
815 */ 842 */
816static void __exit cleanup_pmc551(void) 843static void __exit cleanup_pmc551(void)
817{ 844{
818 int found=0; 845 int found = 0;
819 struct mtd_info *mtd; 846 struct mtd_info *mtd;
820 struct mypriv *priv; 847 struct mypriv *priv;
821 848
822 while((mtd=pmc551list)) { 849 while ((mtd = pmc551list)) {
823 priv = mtd->priv; 850 priv = mtd->priv;
824 pmc551list = priv->nextpmc551; 851 pmc551list = priv->nextpmc551;
825 852
826 if(priv->start) { 853 if (priv->start) {
827 printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n", 854 printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
828 priv->asize>>20, priv->start); 855 "0x%p\n", priv->asize >> 20, priv->start);
829 iounmap (priv->start); 856 pci_iounmap(priv->dev, priv->start);
830 } 857 }
858 pci_dev_put(priv->dev);
831 859
832 kfree (mtd->priv); 860 kfree(mtd->priv);
833 del_mtd_device (mtd); 861 del_mtd_device(mtd);
834 kfree (mtd); 862 kfree(mtd);
835 found++; 863 found++;
836 } 864 }
837 865
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 83d0b2a52527..24747bdc3e19 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -13,13 +13,13 @@ config MTD_COMPLEX_MAPPINGS
13 13
14config MTD_PHYSMAP 14config 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
25config MTD_PHYSMAP_START 25config MTD_PHYSMAP_START
@@ -447,14 +447,6 @@ config MTD_DC21285
447 21285 bridge used with Intel's StrongARM processors. More info at 447 21285 bridge used with Intel's StrongARM processors. More info at
448 <http://www.intel.com/design/bridge/docs/21285_documentation.htm>. 448 <http://www.intel.com/design/bridge/docs/21285_documentation.htm>.
449 449
450config MTD_IQ80310
451 tristate "CFI Flash device mapped on the XScale IQ80310 board"
452 depends on MTD_CFI && ARCH_IQ80310
453 help
454 This enables access routines for the flash chips on the Intel XScale
455 IQ80310 evaluation board. If you have one of these boards and would
456 like to use the flash chips on it, say 'Y'.
457
458config MTD_IXP4XX 450config MTD_IXP4XX
459 tristate "CFI Flash device mapped on Intel IXP4xx based systems" 451 tristate "CFI Flash device mapped on Intel IXP4xx based systems"
460 depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX 452 depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index ab71f172eb77..191c1928bbec 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
15obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o 15obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
16obj-$(CONFIG_MTD_DC21285) += dc21285.o 16obj-$(CONFIG_MTD_DC21285) += dc21285.o
17obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o 17obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
18obj-$(CONFIG_MTD_IQ80310) += iq80310.o
19obj-$(CONFIG_MTD_L440GX) += l440gx.o 18obj-$(CONFIG_MTD_L440GX) += l440gx.o
20obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o 19obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
21obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o 20obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 447955be18af..797caffb20b1 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -57,6 +57,7 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window)
57 /* Disable writes through the rom window */ 57 /* Disable writes through the rom window */
58 pci_read_config_byte(window->pdev, 0x40, &byte); 58 pci_read_config_byte(window->pdev, 0x40, &byte);
59 pci_write_config_byte(window->pdev, 0x40, byte & ~1); 59 pci_write_config_byte(window->pdev, 0x40, byte & ~1);
60 pci_dev_put(window->pdev);
60 } 61 }
61 62
62 /* Free all of the mtd devices */ 63 /* Free all of the mtd devices */
@@ -91,7 +92,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
91 struct amd76xrom_map_info *map = NULL; 92 struct amd76xrom_map_info *map = NULL;
92 unsigned long map_top; 93 unsigned long map_top;
93 94
94 /* Remember the pci dev I find the window in */ 95 /* Remember the pci dev I find the window in - already have a ref */
95 window->pdev = pdev; 96 window->pdev = pdev;
96 97
97 /* Assume the rom window is properly setup, and find it's size */ 98 /* Assume the rom window is properly setup, and find it's size */
@@ -302,7 +303,7 @@ static int __init init_amd76xrom(void)
302 struct pci_device_id *id; 303 struct pci_device_id *id;
303 pdev = NULL; 304 pdev = NULL;
304 for(id = amd76xrom_pci_tbl; id->vendor; id++) { 305 for(id = amd76xrom_pci_tbl; id->vendor; id++) {
305 pdev = pci_find_device(id->vendor, id->device, NULL); 306 pdev = pci_get_device(id->vendor, id->device, NULL);
306 if (pdev) { 307 if (pdev) {
307 break; 308 break;
308 } 309 }
diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
index d95ae582fbe9..642d96bc8919 100644
--- a/drivers/mtd/maps/arctic-mtd.c
+++ b/drivers/mtd/maps/arctic-mtd.c
@@ -96,6 +96,8 @@ static struct mtd_partition arctic_partitions[PARTITIONS] = {
96static int __init 96static int __init
97init_arctic_mtd(void) 97init_arctic_mtd(void)
98{ 98{
99 int err = 0;
100
99 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); 101 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
100 102
101 arctic_mtd_map.virt = ioremap(PADDR, SIZE); 103 arctic_mtd_map.virt = ioremap(PADDR, SIZE);
@@ -109,12 +111,20 @@ init_arctic_mtd(void)
109 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); 111 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
110 arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map); 112 arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
111 113
112 if (!arctic_mtd) 114 if (!arctic_mtd) {
115 iounmap((void *) arctic_mtd_map.virt);
113 return -ENXIO; 116 return -ENXIO;
117 }
114 118
115 arctic_mtd->owner = THIS_MODULE; 119 arctic_mtd->owner = THIS_MODULE;
116 120
117 return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); 121 err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
122 if (err) {
123 printk("%s: add_mtd_partitions failed\n", NAME);
124 iounmap((void *) arctic_mtd_map.virt);
125 }
126
127 return err;
118} 128}
119 129
120static void __exit 130static void __exit
diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c
index 5df7361d1407..a64b1a5ab316 100644
--- a/drivers/mtd/maps/beech-mtd.c
+++ b/drivers/mtd/maps/beech-mtd.c
@@ -72,6 +72,8 @@ static struct mtd_partition beech_partitions[2] = {
72static int __init 72static int __init
73init_beech_mtd(void) 73init_beech_mtd(void)
74{ 74{
75 int err = 0;
76
75 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); 77 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
76 78
77 beech_mtd_map.virt = ioremap(PADDR, SIZE); 79 beech_mtd_map.virt = ioremap(PADDR, SIZE);
@@ -86,12 +88,20 @@ init_beech_mtd(void)
86 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); 88 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
87 beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map); 89 beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
88 90
89 if (!beech_mtd) 91 if (!beech_mtd) {
92 iounmap((void *) beech_mtd_map.virt);
90 return -ENXIO; 93 return -ENXIO;
94 }
91 95
92 beech_mtd->owner = THIS_MODULE; 96 beech_mtd->owner = THIS_MODULE;
93 97
94 return add_mtd_partitions(beech_mtd, beech_partitions, 2); 98 err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
99 if (err) {
100 printk("%s: add_mtd_partitions failed\n", NAME);
101 iounmap((void *) beech_mtd_map.virt);
102 }
103
104 return err;
95} 105}
96 106
97static void __exit 107static void __exit
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
index aa56defb94c8..d6bef100d69a 100644
--- a/drivers/mtd/maps/cstm_mips_ixx.c
+++ b/drivers/mtd/maps/cstm_mips_ixx.c
@@ -171,7 +171,14 @@ int __init init_cstm_mips_ixx(void)
171 cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; 171 cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
172 cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); 172 cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
173 if (!cstm_mips_ixx_map[i].virt) { 173 if (!cstm_mips_ixx_map[i].virt) {
174 int j = 0;
174 printk(KERN_WARNING "Failed to ioremap\n"); 175 printk(KERN_WARNING "Failed to ioremap\n");
176 for (j = 0; j < i; j++) {
177 if (cstm_mips_ixx_map[j].virt) {
178 iounmap((void *)cstm_mips_ixx_map[j].virt);
179 cstm_mips_ixx_map[j].virt = 0;
180 }
181 }
175 return -EIO; 182 return -EIO;
176 } 183 }
177 cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name; 184 cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
@@ -204,8 +211,15 @@ int __init init_cstm_mips_ixx(void)
204 cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; 211 cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
205 add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); 212 add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
206 } 213 }
207 else 214 else {
208 return -ENXIO; 215 for (i = 0; i < PHYSMAP_NUMBER; i++) {
216 if (cstm_mips_ixx_map[i].virt) {
217 iounmap((void *)cstm_mips_ixx_map[i].virt);
218 cstm_mips_ixx_map[i].virt = 0;
219 }
220 }
221 return -ENXIO;
222 }
209 } 223 }
210 return 0; 224 return 0;
211} 225}
diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c
index 641e1dd8479e..1488bb92f26f 100644
--- a/drivers/mtd/maps/ebony.c
+++ b/drivers/mtd/maps/ebony.c
@@ -108,6 +108,7 @@ int __init init_ebony(void)
108 ARRAY_SIZE(ebony_small_partitions)); 108 ARRAY_SIZE(ebony_small_partitions));
109 } else { 109 } else {
110 printk("map probe failed for flash\n"); 110 printk("map probe failed for flash\n");
111 iounmap(ebony_small_map.virt);
111 return -ENXIO; 112 return -ENXIO;
112 } 113 }
113 114
@@ -117,6 +118,7 @@ int __init init_ebony(void)
117 118
118 if (!ebony_large_map.virt) { 119 if (!ebony_large_map.virt) {
119 printk("Failed to ioremap flash\n"); 120 printk("Failed to ioremap flash\n");
121 iounmap(ebony_small_map.virt);
120 return -EIO; 122 return -EIO;
121 } 123 }
122 124
@@ -129,6 +131,8 @@ int __init init_ebony(void)
129 ARRAY_SIZE(ebony_large_partitions)); 131 ARRAY_SIZE(ebony_large_partitions));
130 } else { 132 } else {
131 printk("map probe failed for flash\n"); 133 printk("map probe failed for flash\n");
134 iounmap(ebony_small_map.virt);
135 iounmap(ebony_large_map.virt);
132 return -ENXIO; 136 return -ENXIO;
133 } 137 }
134 138
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
index c6bf4e1219ef..7c50c271651c 100644
--- a/drivers/mtd/maps/fortunet.c
+++ b/drivers/mtd/maps/fortunet.c
@@ -218,8 +218,11 @@ int __init init_fortunet(void)
218 map_regions[ix].map_info.size); 218 map_regions[ix].map_info.size);
219 if(!map_regions[ix].map_info.virt) 219 if(!map_regions[ix].map_info.virt)
220 { 220 {
221 int j = 0;
221 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", 222 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
222 map_regions[ix].map_info.name); 223 map_regions[ix].map_info.name);
224 for (j = 0 ; j < ix; j++)
225 iounmap(map_regions[j].map_info.virt);
223 return -ENXIO; 226 return -ENXIO;
224 } 227 }
225 simple_map_init(&map_regions[ix].map_info); 228 simple_map_init(&map_regions[ix].map_info);
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index db4b570d874a..2bb3e63606e5 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -61,6 +61,7 @@ static void ichxrom_cleanup(struct ichxrom_window *window)
61 /* Disable writes through the rom window */ 61 /* Disable writes through the rom window */
62 pci_read_config_word(window->pdev, BIOS_CNTL, &word); 62 pci_read_config_word(window->pdev, BIOS_CNTL, &word);
63 pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1); 63 pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
64 pci_dev_put(window->pdev);
64 65
65 /* Free all of the mtd devices */ 66 /* Free all of the mtd devices */
66 list_for_each_entry_safe(map, scratch, &window->maps, list) { 67 list_for_each_entry_safe(map, scratch, &window->maps, list) {
@@ -355,7 +356,7 @@ static int __init init_ichxrom(void)
355 356
356 pdev = NULL; 357 pdev = NULL;
357 for (id = ichxrom_pci_tbl; id->vendor; id++) { 358 for (id = ichxrom_pci_tbl; id->vendor; id++) {
358 pdev = pci_find_device(id->vendor, id->device, NULL); 359 pdev = pci_get_device(id->vendor, id->device, NULL);
359 if (pdev) { 360 if (pdev) {
360 break; 361 break;
361 } 362 }
diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c
deleted file mode 100644
index 62d9e87d84e2..000000000000
--- a/drivers/mtd/maps/iq80310.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * $Id: iq80310.c,v 1.21 2005/11/07 11:14:27 gleixner Exp $
3 *
4 * Mapping for the Intel XScale IQ80310 evaluation board
5 *
6 * Author: Nicolas Pitre
7 * Copyright: (C) 2001 MontaVista Software Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <asm/io.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23
24
25#define WINDOW_ADDR 0
26#define WINDOW_SIZE 8*1024*1024
27#define BUSWIDTH 1
28
29static struct mtd_info *mymtd;
30
31static struct map_info iq80310_map = {
32 .name = "IQ80310 flash",
33 .size = WINDOW_SIZE,
34 .bankwidth = BUSWIDTH,
35 .phys = WINDOW_ADDR
36};
37
38static struct mtd_partition iq80310_partitions[4] = {
39 {
40 .name = "Firmware",
41 .size = 0x00080000,
42 .offset = 0,
43 .mask_flags = MTD_WRITEABLE /* force read-only */
44 },{
45 .name = "Kernel",
46 .size = 0x000a0000,
47 .offset = 0x00080000,
48 },{
49 .name = "Filesystem",
50 .size = 0x00600000,
51 .offset = 0x00120000
52 },{
53 .name = "RedBoot",
54 .size = 0x000e0000,
55 .offset = 0x00720000,
56 .mask_flags = MTD_WRITEABLE
57 }
58};
59
60static struct mtd_info *mymtd;
61static struct mtd_partition *parsed_parts;
62static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
63
64static int __init init_iq80310(void)
65{
66 struct mtd_partition *parts;
67 int nb_parts = 0;
68 int parsed_nr_parts = 0;
69 int ret;
70
71 iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
72 if (!iq80310_map.virt) {
73 printk("Failed to ioremap\n");
74 return -EIO;
75 }
76 simple_map_init(&iq80310_map);
77
78 mymtd = do_map_probe("cfi_probe", &iq80310_map);
79 if (!mymtd) {
80 iounmap((void *)iq80310_map.virt);
81 return -ENXIO;
82 }
83 mymtd->owner = THIS_MODULE;
84
85 ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
86
87 if (ret > 0)
88 parsed_nr_parts = ret;
89
90 if (parsed_nr_parts > 0) {
91 parts = parsed_parts;
92 nb_parts = parsed_nr_parts;
93 } else {
94 parts = iq80310_partitions;
95 nb_parts = ARRAY_SIZE(iq80310_partitions);
96 }
97 add_mtd_partitions(mymtd, parts, nb_parts);
98 return 0;
99}
100
101static void __exit cleanup_iq80310(void)
102{
103 if (mymtd) {
104 del_mtd_partitions(mymtd);
105 map_destroy(mymtd);
106 kfree(parsed_parts);
107 }
108 if (iq80310_map.virt)
109 iounmap((void *)iq80310_map.virt);
110}
111
112module_init(init_iq80310);
113module_exit(cleanup_iq80310);
114
115
116MODULE_LICENSE("GPL");
117MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
118MODULE_DESCRIPTION("MTD map driver for Intel XScale IQ80310 evaluation board");
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 986c58628390..7a828e3e6446 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -253,7 +253,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
253 /* Use the fast version */ 253 /* Use the fast version */
254 info->map.write = ixp4xx_write16, 254 info->map.write = ixp4xx_write16,
255 255
256 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); 256 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start);
257 if (err > 0) { 257 if (err > 0) {
258 err = add_mtd_partitions(info->mtd, info->partitions, err); 258 err = add_mtd_partitions(info->mtd, info->partitions, err);
259 if(err) 259 if(err)
diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c
index 6b784ef5ee70..67620adf4811 100644
--- a/drivers/mtd/maps/l440gx.c
+++ b/drivers/mtd/maps/l440gx.c
@@ -61,14 +61,17 @@ static int __init init_l440gx(void)
61 struct resource *pm_iobase; 61 struct resource *pm_iobase;
62 __u16 word; 62 __u16 word;
63 63
64 dev = pci_find_device(PCI_VENDOR_ID_INTEL, 64 dev = pci_get_device(PCI_VENDOR_ID_INTEL,
65 PCI_DEVICE_ID_INTEL_82371AB_0, NULL); 65 PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
66 66
67 pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, 67 pm_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
68 PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 68 PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
69 69
70 pci_dev_put(dev);
71
70 if (!dev || !pm_dev) { 72 if (!dev || !pm_dev) {
71 printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n"); 73 printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n");
74 pci_dev_put(pm_dev);
72 return -ENODEV; 75 return -ENODEV;
73 } 76 }
74 77
@@ -76,6 +79,7 @@ static int __init init_l440gx(void)
76 79
77 if (!l440gx_map.virt) { 80 if (!l440gx_map.virt) {
78 printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); 81 printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
82 pci_dev_put(pm_dev);
79 return -ENOMEM; 83 return -ENOMEM;
80 } 84 }
81 simple_map_init(&l440gx_map); 85 simple_map_init(&l440gx_map);
@@ -99,8 +103,12 @@ static int __init init_l440gx(void)
99 pm_iobase->start += iobase & ~1; 103 pm_iobase->start += iobase & ~1;
100 pm_iobase->end += iobase & ~1; 104 pm_iobase->end += iobase & ~1;
101 105
106 pci_dev_put(pm_dev);
107
102 /* Allocate the resource region */ 108 /* Allocate the resource region */
103 if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) { 109 if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
110 pci_dev_put(dev);
111 pci_dev_put(pm_dev);
104 printk(KERN_WARNING "Could not allocate pm iobase resource\n"); 112 printk(KERN_WARNING "Could not allocate pm iobase resource\n");
105 iounmap(l440gx_map.virt); 113 iounmap(l440gx_map.virt);
106 return -ENXIO; 114 return -ENXIO;
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
index 1c13d2dc0cdf..e34376321050 100644
--- a/drivers/mtd/maps/lasat.c
+++ b/drivers/mtd/maps/lasat.c
@@ -79,6 +79,7 @@ static int __init init_lasat(void)
79 return 0; 79 return 0;
80 } 80 }
81 81
82 iounmap(lasat_map.virt);
82 return -ENXIO; 83 return -ENXIO;
83} 84}
84 85
@@ -89,6 +90,7 @@ static void __exit cleanup_lasat(void)
89 map_destroy(lasat_mtd); 90 map_destroy(lasat_mtd);
90 } 91 }
91 if (lasat_map.virt) { 92 if (lasat_map.virt) {
93 iounmap(lasat_map.virt);
92 lasat_map.virt = 0; 94 lasat_map.virt = 0;
93 } 95 }
94} 96}
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index 0994b5b2e331..198e840ff6db 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -277,6 +277,7 @@ int __init nettel_init(void)
277 nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); 277 nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
278 if (!nettel_amd_map.virt) { 278 if (!nettel_amd_map.virt) {
279 printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); 279 printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
280 iounmap(nettel_mmcrp);
280 return(-EIO); 281 return(-EIO);
281 } 282 }
282 simple_map_init(&nettel_amd_map); 283 simple_map_init(&nettel_amd_map);
@@ -337,7 +338,8 @@ int __init nettel_init(void)
337 nettel_amd_map.virt = NULL; 338 nettel_amd_map.virt = NULL;
338#else 339#else
339 /* Only AMD flash supported */ 340 /* Only AMD flash supported */
340 return(-ENXIO); 341 rc = -ENXIO;
342 goto out_unmap2;
341#endif 343#endif
342 } 344 }
343 345
@@ -361,14 +363,15 @@ int __init nettel_init(void)
361 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 363 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
362 if (!nettel_intel_map.virt) { 364 if (!nettel_intel_map.virt) {
363 printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); 365 printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
364 return(-EIO); 366 rc = -EIO;
367 goto out_unmap2;
365 } 368 }
366 simple_map_init(&nettel_intel_map); 369 simple_map_init(&nettel_intel_map);
367 370
368 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 371 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
369 if (!intel_mtd) { 372 if (!intel_mtd) {
370 iounmap(nettel_intel_map.virt); 373 rc = -ENXIO;
371 return(-ENXIO); 374 goto out_unmap1;
372 } 375 }
373 376
374 /* Set PAR to the detected size */ 377 /* Set PAR to the detected size */
@@ -394,13 +397,14 @@ int __init nettel_init(void)
394 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); 397 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
395 if (!nettel_intel_map.virt) { 398 if (!nettel_intel_map.virt) {
396 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); 399 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
397 return(-EIO); 400 rc = -EIO;
401 goto out_unmap2;
398 } 402 }
399 403
400 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); 404 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
401 if (! intel_mtd) { 405 if (! intel_mtd) {
402 iounmap((void *) nettel_intel_map.virt); 406 rc = -ENXIO;
403 return(-ENXIO); 407 goto out_unmap1;
404 } 408 }
405 409
406 intel1size = intel_mtd->size - intel0size; 410 intel1size = intel_mtd->size - intel0size;
@@ -456,6 +460,18 @@ int __init nettel_init(void)
456#endif 460#endif
457 461
458 return(rc); 462 return(rc);
463
464#ifdef CONFIG_MTD_CFI_INTELEXT
465out_unmap1:
466 iounmap((void *) nettel_intel_map.virt);
467#endif
468
469out_unmap2:
470 iounmap(nettel_mmcrp);
471 iounmap(nettel_amd_map.virt);
472
473 return(rc);
474
459} 475}
460 476
461/****************************************************************************/ 477/****************************************************************************/
@@ -469,6 +485,10 @@ void __exit nettel_cleanup(void)
469 del_mtd_partitions(amd_mtd); 485 del_mtd_partitions(amd_mtd);
470 map_destroy(amd_mtd); 486 map_destroy(amd_mtd);
471 } 487 }
488 if (nettel_mmcrp) {
489 iounmap(nettel_mmcrp);
490 nettel_mmcrp = NULL;
491 }
472 if (nettel_amd_map.virt) { 492 if (nettel_amd_map.virt) {
473 iounmap(nettel_amd_map.virt); 493 iounmap(nettel_amd_map.virt);
474 nettel_amd_map.virt = NULL; 494 nettel_amd_map.virt = NULL;
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c
index 2f07602ba940..5522eac8c980 100644
--- a/drivers/mtd/maps/ocotea.c
+++ b/drivers/mtd/maps/ocotea.c
@@ -97,6 +97,7 @@ int __init init_ocotea(void)
97 ARRAY_SIZE(ocotea_small_partitions)); 97 ARRAY_SIZE(ocotea_small_partitions));
98 } else { 98 } else {
99 printk("map probe failed for flash\n"); 99 printk("map probe failed for flash\n");
100 iounmap(ocotea_small_map.virt);
100 return -ENXIO; 101 return -ENXIO;
101 } 102 }
102 103
@@ -106,6 +107,7 @@ int __init init_ocotea(void)
106 107
107 if (!ocotea_large_map.virt) { 108 if (!ocotea_large_map.virt) {
108 printk("Failed to ioremap flash\n"); 109 printk("Failed to ioremap flash\n");
110 iounmap(ocotea_small_map.virt);
109 return -EIO; 111 return -EIO;
110 } 112 }
111 113
@@ -118,6 +120,8 @@ int __init init_ocotea(void)
118 ARRAY_SIZE(ocotea_large_partitions)); 120 ARRAY_SIZE(ocotea_large_partitions));
119 } else { 121 } else {
120 printk("map probe failed for flash\n"); 122 printk("map probe failed for flash\n");
123 iounmap(ocotea_small_map.virt);
124 iounmap(ocotea_large_map.virt);
121 return -ENXIO; 125 return -ENXIO;
122 } 126 }
123 127
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index c861134cbc48..995347b1beba 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -602,6 +602,10 @@ static int pcmciamtd_config(struct pcmcia_device *link)
602 ret = pcmcia_request_configuration(link, &link->conf); 602 ret = pcmcia_request_configuration(link, &link->conf);
603 if(ret != CS_SUCCESS) { 603 if(ret != CS_SUCCESS) {
604 cs_error(link, RequestConfiguration, ret); 604 cs_error(link, RequestConfiguration, ret);
605 if (dev->win_base) {
606 iounmap(dev->win_base);
607 dev->win_base = NULL;
608 }
605 return -ENODEV; 609 return -ENODEV;
606 } 610 }
607 611
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 7799a25a7f2a..bc7cc71788bc 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -158,9 +158,42 @@ err_out:
158 return err; 158 return err;
159} 159}
160 160
161#ifdef CONFIG_PM
162static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state)
163{
164 struct physmap_flash_info *info = platform_get_drvdata(dev);
165 int ret = 0;
166
167 if (info)
168 ret = info->mtd->suspend(info->mtd);
169
170 return ret;
171}
172
173static int physmap_flash_resume(struct platform_device *dev)
174{
175 struct physmap_flash_info *info = platform_get_drvdata(dev);
176 if (info)
177 info->mtd->resume(info->mtd);
178 return 0;
179}
180
181static void physmap_flash_shutdown(struct platform_device *dev)
182{
183 struct physmap_flash_info *info = platform_get_drvdata(dev);
184 if (info && info->mtd->suspend(info->mtd) == 0)
185 info->mtd->resume(info->mtd);
186}
187#endif
188
161static struct platform_driver physmap_flash_driver = { 189static struct platform_driver physmap_flash_driver = {
162 .probe = physmap_flash_probe, 190 .probe = physmap_flash_probe,
163 .remove = physmap_flash_remove, 191 .remove = physmap_flash_remove,
192#ifdef CONFIG_PM
193 .suspend = physmap_flash_suspend,
194 .resume = physmap_flash_resume,
195 .shutdown = physmap_flash_shutdown,
196#endif
164 .driver = { 197 .driver = {
165 .name = "physmap-flash", 198 .name = "physmap-flash",
166 }, 199 },
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
index ec8fdae1dd99..2257d2b500c0 100644
--- a/drivers/mtd/maps/redwood.c
+++ b/drivers/mtd/maps/redwood.c
@@ -126,6 +126,8 @@ static struct mtd_info *redwood_mtd;
126 126
127int __init init_redwood_flash(void) 127int __init init_redwood_flash(void)
128{ 128{
129 int err = 0;
130
129 printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", 131 printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
130 WINDOW_SIZE, WINDOW_ADDR); 132 WINDOW_SIZE, WINDOW_ADDR);
131 133
@@ -141,11 +143,18 @@ int __init init_redwood_flash(void)
141 143
142 if (redwood_mtd) { 144 if (redwood_mtd) {
143 redwood_mtd->owner = THIS_MODULE; 145 redwood_mtd->owner = THIS_MODULE;
144 return add_mtd_partitions(redwood_mtd, 146 err = add_mtd_partitions(redwood_mtd,
145 redwood_flash_partitions, 147 redwood_flash_partitions,
146 NUM_REDWOOD_FLASH_PARTITIONS); 148 NUM_REDWOOD_FLASH_PARTITIONS);
149 if (err) {
150 printk("init_redwood_flash: add_mtd_partitions failed\n");
151 iounmap(redwood_flash_map.virt);
152 }
153 return err;
154
147 } 155 }
148 156
157 iounmap(redwood_flash_map.virt);
149 return -ENXIO; 158 return -ENXIO;
150} 159}
151 160
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
index 7d0fcf8f4f33..b8c1331b7a04 100644
--- a/drivers/mtd/maps/sbc8240.c
+++ b/drivers/mtd/maps/sbc8240.c
@@ -156,7 +156,7 @@ int __init init_sbc8240_mtd (void)
156 }; 156 };
157 157
158 int devicesfound = 0; 158 int devicesfound = 0;
159 int i; 159 int i,j;
160 160
161 for (i = 0; i < NUM_FLASH_BANKS; i++) { 161 for (i = 0; i < NUM_FLASH_BANKS; i++) {
162 printk (KERN_NOTICE MSG_PREFIX 162 printk (KERN_NOTICE MSG_PREFIX
@@ -166,6 +166,10 @@ int __init init_sbc8240_mtd (void)
166 (unsigned long) ioremap (pt[i].addr, pt[i].size); 166 (unsigned long) ioremap (pt[i].addr, pt[i].size);
167 if (!sbc8240_map[i].map_priv_1) { 167 if (!sbc8240_map[i].map_priv_1) {
168 printk (MSG_PREFIX "failed to ioremap\n"); 168 printk (MSG_PREFIX "failed to ioremap\n");
169 for (j = 0; j < i; j++) {
170 iounmap((void *) sbc8240_map[j].map_priv_1);
171 sbc8240_map[j].map_priv_1 = 0;
172 }
169 return -EIO; 173 return -EIO;
170 } 174 }
171 simple_map_init(&sbc8240_mtd[i]); 175 simple_map_init(&sbc8240_mtd[i]);
@@ -175,6 +179,11 @@ int __init init_sbc8240_mtd (void)
175 if (sbc8240_mtd[i]) { 179 if (sbc8240_mtd[i]) {
176 sbc8240_mtd[i]->module = THIS_MODULE; 180 sbc8240_mtd[i]->module = THIS_MODULE;
177 devicesfound++; 181 devicesfound++;
182 } else {
183 if (sbc8240_map[i].map_priv_1) {
184 iounmap((void *) sbc8240_map[i].map_priv_1);
185 sbc8240_map[i].map_priv_1 = 0;
186 }
178 } 187 }
179 } 188 }
180 189
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
index 7391fd544e86..5e2bce22f37c 100644
--- a/drivers/mtd/maps/scx200_docflash.c
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -87,19 +87,23 @@ static int __init init_scx200_docflash(void)
87 87
88 printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n"); 88 printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n");
89 89
90 if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, 90 if ((bridge = pci_get_device(PCI_VENDOR_ID_NS,
91 PCI_DEVICE_ID_NS_SCx200_BRIDGE, 91 PCI_DEVICE_ID_NS_SCx200_BRIDGE,
92 NULL)) == NULL) 92 NULL)) == NULL)
93 return -ENODEV; 93 return -ENODEV;
94 94
95 /* check that we have found the configuration block */ 95 /* check that we have found the configuration block */
96 if (!scx200_cb_present()) 96 if (!scx200_cb_present()) {
97 pci_dev_put(bridge);
97 return -ENODEV; 98 return -ENODEV;
99 }
98 100
99 if (probe) { 101 if (probe) {
100 /* Try to use the present flash mapping if any */ 102 /* Try to use the present flash mapping if any */
101 pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base); 103 pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
102 pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl); 104 pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
105 pci_dev_put(bridge);
106
103 pmr = inl(scx200_cb_base + SCx200_PMR); 107 pmr = inl(scx200_cb_base + SCx200_PMR);
104 108
105 if (base == 0 109 if (base == 0
@@ -127,6 +131,7 @@ static int __init init_scx200_docflash(void)
127 return -ENOMEM; 131 return -ENOMEM;
128 } 132 }
129 } else { 133 } else {
134 pci_dev_put(bridge);
130 for (u = size; u > 1; u >>= 1) 135 for (u = size; u > 1; u >>= 1)
131 ; 136 ;
132 if (u != 1) { 137 if (u != 1) {
diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c
index ec80eec376bf..ca932122fb64 100644
--- a/drivers/mtd/maps/walnut.c
+++ b/drivers/mtd/maps/walnut.c
@@ -68,6 +68,7 @@ int __init init_walnut(void)
68 68
69 if (WALNUT_FLASH_ONBD_N(fpga_brds1)) { 69 if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
70 printk("The on-board flash is disabled (U79 sw 5)!"); 70 printk("The on-board flash is disabled (U79 sw 5)!");
71 iounmap(fpga_status_adr);
71 return -EIO; 72 return -EIO;
72 } 73 }
73 if (WALNUT_FLASH_SRAM_SEL(fpga_brds1)) 74 if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
@@ -81,6 +82,7 @@ int __init init_walnut(void)
81 82
82 if (!walnut_map.virt) { 83 if (!walnut_map.virt) {
83 printk("Failed to ioremap flash.\n"); 84 printk("Failed to ioremap flash.\n");
85 iounmap(fpga_status_adr);
84 return -EIO; 86 return -EIO;
85 } 87 }
86 88
@@ -93,9 +95,11 @@ int __init init_walnut(void)
93 ARRAY_SIZE(walnut_partitions)); 95 ARRAY_SIZE(walnut_partitions));
94 } else { 96 } else {
95 printk("map probe failed for flash\n"); 97 printk("map probe failed for flash\n");
98 iounmap(fpga_status_adr);
96 return -ENXIO; 99 return -ENXIO;
97 } 100 }
98 101
102 iounmap(fpga_status_adr);
99 return 0; 103 return 0;
100} 104}
101 105
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index fb8b4f7e48d3..5b6acfcb2b88 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -62,15 +62,12 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
62 struct mtd_info *mtd = mfi->mtd; 62 struct mtd_info *mtd = mfi->mtd;
63 63
64 switch (orig) { 64 switch (orig) {
65 case 0: 65 case SEEK_SET:
66 /* SEEK_SET */
67 break; 66 break;
68 case 1: 67 case SEEK_CUR:
69 /* SEEK_CUR */
70 offset += file->f_pos; 68 offset += file->f_pos;
71 break; 69 break;
72 case 2: 70 case SEEK_END:
73 /* SEEK_END */
74 offset += mtd->size; 71 offset += mtd->size;
75 break; 72 break;
76 default: 73 default:
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 168d3ba063c3..c4d26de74349 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -57,6 +57,16 @@ int add_mtd_device(struct mtd_info *mtd)
57 mtd->index = i; 57 mtd->index = i;
58 mtd->usecount = 0; 58 mtd->usecount = 0;
59 59
60 /* Some chips always power up locked. Unlock them now */
61 if ((mtd->flags & MTD_WRITEABLE)
62 && (mtd->flags & MTD_STUPID_LOCK) && mtd->unlock) {
63 if (mtd->unlock(mtd, 0, mtd->size))
64 printk(KERN_WARNING
65 "%s: unlock failed, "
66 "writes may not work\n",
67 mtd->name);
68 }
69
60 DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); 70 DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
61 /* No need to get a refcount on the module containing 71 /* No need to get a refcount on the module containing
62 the notifier, since we hold the mtd_table_mutex */ 72 the notifier, since we hold the mtd_table_mutex */
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
16config MTD_NAND_VERIFY_WRITE 16config MTD_NAND_VERIFY_WRITE
17 bool "Verify NAND page writes" 17 bool "Verify NAND page writes"
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 31228334da12..09e421a96893 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -21,18 +21,7 @@
21#include <linux/version.h> 21#include <linux/version.h>
22#include <asm/io.h> 22#include <asm/io.h>
23 23
24/* fixme: this is ugly */
25#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
26#include <asm/mach-au1x00/au1xxx.h> 24#include <asm/mach-au1x00/au1xxx.h>
27#else
28#include <asm/au1000.h>
29#ifdef CONFIG_MIPS_PB1550
30#include <asm/pb1550.h>
31#endif
32#ifdef CONFIG_MIPS_DB1550
33#include <asm/db1x00.h>
34#endif
35#endif
36 25
37/* 26/*
38 * MTD structure for NAND controller 27 * MTD structure for NAND controller
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 516c0e5e564c..12017f3c6bd6 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -198,6 +198,9 @@ static void __exit ep7312_cleanup(void)
198 /* Release resources, unregister device */ 198 /* Release resources, unregister device */
199 nand_release(ap7312_mtd); 199 nand_release(ap7312_mtd);
200 200
201 /* Release io resource */
202 iounmap((void *)this->IO_ADDR_R);
203
201 /* Free the MTD device structure */ 204 /* Free the MTD device structure */
202 kfree(ep7312_mtd); 205 kfree(ep7312_mtd);
203} 206}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 0a54d003ef34..975b2ef61121 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -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/ndfc.c b/drivers/mtd/nand/ndfc.c
index e5bd88f2d560..039c759cfbfc 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -168,7 +168,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
168 chip->ecc.mode = NAND_ECC_HW; 168 chip->ecc.mode = NAND_ECC_HW;
169 chip->ecc.size = 256; 169 chip->ecc.size = 256;
170 chip->ecc.bytes = 3; 170 chip->ecc.bytes = 3;
171 chip->ecclayout = mtd->pl_chip->ecclayout; 171 chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
172 mtd->mtd.priv = chip; 172 mtd->mtd.priv = chip;
173 mtd->mtd.owner = THIS_MODULE; 173 mtd->mtd.owner = THIS_MODULE;
174} 174}
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 22fa65c12ab9..eb7d4d443deb 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -276,6 +276,7 @@ static int __init ppchameleonevb_init(void)
276 /* Scan to find existence of the device (it could not be mounted) */ 276 /* Scan to find existence of the device (it could not be mounted) */
277 if (nand_scan(ppchameleon_mtd, 1)) { 277 if (nand_scan(ppchameleon_mtd, 1)) {
278 iounmap((void *)ppchameleon_fio_base); 278 iounmap((void *)ppchameleon_fio_base);
279 ppchameleon_fio_base = NULL;
279 kfree(ppchameleon_mtd); 280 kfree(ppchameleon_mtd);
280 goto nand_evb_init; 281 goto nand_evb_init;
281 } 282 }
@@ -314,6 +315,8 @@ static int __init ppchameleonevb_init(void)
314 ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); 315 ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
315 if (!ppchameleonevb_mtd) { 316 if (!ppchameleonevb_mtd) {
316 printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); 317 printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
318 if (ppchameleon_fio_base)
319 iounmap(ppchameleon_fio_base);
317 return -ENOMEM; 320 return -ENOMEM;
318 } 321 }
319 322
@@ -322,6 +325,8 @@ static int __init ppchameleonevb_init(void)
322 if (!ppchameleonevb_fio_base) { 325 if (!ppchameleonevb_fio_base) {
323 printk("ioremap PPChameleonEVB NAND flash failed\n"); 326 printk("ioremap PPChameleonEVB NAND flash failed\n");
324 kfree(ppchameleonevb_mtd); 327 kfree(ppchameleonevb_mtd);
328 if (ppchameleon_fio_base)
329 iounmap(ppchameleon_fio_base);
325 return -EIO; 330 return -EIO;
326 } 331 }
327 332
@@ -378,6 +383,8 @@ static int __init ppchameleonevb_init(void)
378 if (nand_scan(ppchameleonevb_mtd, 1)) { 383 if (nand_scan(ppchameleonevb_mtd, 1)) {
379 iounmap((void *)ppchameleonevb_fio_base); 384 iounmap((void *)ppchameleonevb_fio_base);
380 kfree(ppchameleonevb_mtd); 385 kfree(ppchameleonevb_mtd);
386 if (ppchameleon_fio_base)
387 iounmap(ppchameleon_fio_base);
381 return -ENXIO; 388 return -ENXIO;
382 } 389 }
383#ifdef CONFIG_MTD_PARTITIONS 390#ifdef CONFIG_MTD_PARTITIONS
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/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
new file mode 100644
index 000000000000..ddbf015f4119
--- /dev/null
+++ b/drivers/mtd/ssfdc.c
@@ -0,0 +1,468 @@
1/*
2 * Linux driver for SSFDC Flash Translation Layer (Read only)
3 * (c) 2005 Eptar srl
4 * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
5 *
6 * Based on NTFL and MTDBLOCK_RO drivers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/hdreg.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/nand.h>
21#include <linux/mtd/blktrans.h>
22
23struct ssfdcr_record {
24 struct mtd_blktrans_dev mbd;
25 int usecount;
26 unsigned char heads;
27 unsigned char sectors;
28 unsigned short cylinders;
29 int cis_block; /* block n. containing CIS/IDI */
30 int erase_size; /* phys_block_size */
31 unsigned short *logic_block_map; /* all zones (max 8192 phys blocks on
32 the 128MB) */
33 int map_len; /* n. phys_blocks on the card */
34};
35
36#define SSFDCR_MAJOR 257
37#define SSFDCR_PARTN_BITS 3
38
39#define SECTOR_SIZE 512
40#define SECTOR_SHIFT 9
41#define OOB_SIZE 16
42
43#define MAX_LOGIC_BLK_PER_ZONE 1000
44#define MAX_PHYS_BLK_PER_ZONE 1024
45
46#define KB(x) ( (x) * 1024L )
47#define MB(x) ( KB(x) * 1024L )
48
49/** CHS Table
50 1MB 2MB 4MB 8MB 16MB 32MB 64MB 128MB
51NCylinder 125 125 250 250 500 500 500 500
52NHead 4 4 4 4 4 8 8 16
53NSector 4 8 8 16 16 16 32 32
54SumSector 2,000 4,000 8,000 16,000 32,000 64,000 128,000 256,000
55SectorSize 512 512 512 512 512 512 512 512
56**/
57
58typedef struct {
59 unsigned long size;
60 unsigned short cyl;
61 unsigned char head;
62 unsigned char sec;
63} chs_entry_t;
64
65/* Must be ordered by size */
66static const chs_entry_t chs_table[] = {
67 { MB( 1), 125, 4, 4 },
68 { MB( 2), 125, 4, 8 },
69 { MB( 4), 250, 4, 8 },
70 { MB( 8), 250, 4, 16 },
71 { MB( 16), 500, 4, 16 },
72 { MB( 32), 500, 8, 16 },
73 { MB( 64), 500, 8, 32 },
74 { MB(128), 500, 16, 32 },
75 { 0 },
76};
77
78static int get_chs(unsigned long size, unsigned short *cyl, unsigned char *head,
79 unsigned char *sec)
80{
81 int k;
82 int found = 0;
83
84 k = 0;
85 while (chs_table[k].size > 0 && size > chs_table[k].size)
86 k++;
87
88 if (chs_table[k].size > 0) {
89 if (cyl)
90 *cyl = chs_table[k].cyl;
91 if (head)
92 *head = chs_table[k].head;
93 if (sec)
94 *sec = chs_table[k].sec;
95 found = 1;
96 }
97
98 return found;
99}
100
101/* These bytes are the signature for the CIS/IDI sector */
102static const uint8_t cis_numbers[] = {
103 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20
104};
105
106/* Read and check for a valid CIS sector */
107static int get_valid_cis_sector(struct mtd_info *mtd)
108{
109 int ret, k, cis_sector;
110 size_t retlen;
111 loff_t offset;
112 uint8_t sect_buf[SECTOR_SIZE];
113
114 /*
115 * Look for CIS/IDI sector on the first GOOD block (give up after 4 bad
116 * blocks). If the first good block doesn't contain CIS number the flash
117 * is not SSFDC formatted
118 */
119 cis_sector = -1;
120 for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) {
121 if (!mtd->block_isbad(mtd, offset)) {
122 ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen,
123 sect_buf);
124
125 /* CIS pattern match on the sector buffer */
126 if ( ret < 0 || retlen != SECTOR_SIZE ) {
127 printk(KERN_WARNING
128 "SSFDC_RO:can't read CIS/IDI sector\n");
129 } else if ( !memcmp(sect_buf, cis_numbers,
130 sizeof(cis_numbers)) ) {
131 /* Found */
132 cis_sector = (int)(offset >> SECTOR_SHIFT);
133 } else {
134 DEBUG(MTD_DEBUG_LEVEL1,
135 "SSFDC_RO: CIS/IDI sector not found"
136 " on %s (mtd%d)\n", mtd->name,
137 mtd->index);
138 }
139 break;
140 }
141 }
142
143 return cis_sector;
144}
145
146/* Read physical sector (wrapper to MTD_READ) */
147static int read_physical_sector(struct mtd_info *mtd, uint8_t *sect_buf,
148 int sect_no)
149{
150 int ret;
151 size_t retlen;
152 loff_t offset = (loff_t)sect_no << SECTOR_SHIFT;
153
154 ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, sect_buf);
155 if (ret < 0 || retlen != SECTOR_SIZE)
156 return -1;
157
158 return 0;
159}
160
161/* Read redundancy area (wrapper to MTD_READ_OOB */
162static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
163{
164 struct mtd_oob_ops ops;
165 int ret;
166
167 ops.mode = MTD_OOB_RAW;
168 ops.ooboffs = 0;
169 ops.ooblen = mtd->oobsize;
170 ops.len = OOB_SIZE;
171 ops.oobbuf = buf;
172 ops.datbuf = NULL;
173
174 ret = mtd->read_oob(mtd, offs, &ops);
175 if (ret < 0 || ops.retlen != OOB_SIZE)
176 return -1;
177
178 return 0;
179}
180
181/* Parity calculator on a word of n bit size */
182static int get_parity(int number, int size)
183{
184 int k;
185 int parity;
186
187 parity = 1;
188 for (k = 0; k < size; k++) {
189 parity += (number >> k);
190 parity &= 1;
191 }
192 return parity;
193}
194
195/* Read and validate the logical block address field stored in the OOB */
196static int get_logical_address(uint8_t *oob_buf)
197{
198 int block_address, parity;
199 int offset[2] = {6, 11}; /* offset of the 2 address fields within OOB */
200 int j;
201 int ok = 0;
202
203 /*
204 * Look for the first valid logical address
205 * Valid address has fixed pattern on most significant bits and
206 * parity check
207 */
208 for (j = 0; j < ARRAY_SIZE(offset); j++) {
209 block_address = ((int)oob_buf[offset[j]] << 8) |
210 oob_buf[offset[j]+1];
211
212 /* Check for the signature bits in the address field (MSBits) */
213 if ((block_address & ~0x7FF) == 0x1000) {
214 parity = block_address & 0x01;
215 block_address &= 0x7FF;
216 block_address >>= 1;
217
218 if (get_parity(block_address, 10) != parity) {
219 DEBUG(MTD_DEBUG_LEVEL0,
220 "SSFDC_RO: logical address field%d"
221 "parity error(0x%04X)\n", j+1,
222 block_address);
223 } else {
224 ok = 1;
225 break;
226 }
227 }
228 }
229
230 if ( !ok )
231 block_address = -2;
232
233 DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n",
234 block_address);
235
236 return block_address;
237}
238
239/* Build the logic block map */
240static int build_logical_block_map(struct ssfdcr_record *ssfdc)
241{
242 unsigned long offset;
243 uint8_t oob_buf[OOB_SIZE];
244 int ret, block_address, phys_block;
245 struct mtd_info *mtd = ssfdc->mbd.mtd;
246
247 DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n",
248 ssfdc->map_len, (unsigned long)ssfdc->map_len *
249 ssfdc->erase_size / 1024 );
250
251 /* Scan every physical block, skip CIS block */
252 for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len;
253 phys_block++) {
254 offset = (unsigned long)phys_block * ssfdc->erase_size;
255 if (mtd->block_isbad(mtd, offset))
256 continue; /* skip bad blocks */
257
258 ret = read_raw_oob(mtd, offset, oob_buf);
259 if (ret < 0) {
260 DEBUG(MTD_DEBUG_LEVEL0,
261 "SSFDC_RO: mtd read_oob() failed at %lu\n",
262 offset);
263 return -1;
264 }
265 block_address = get_logical_address(oob_buf);
266
267 /* Skip invalid addresses */
268 if (block_address >= 0 &&
269 block_address < MAX_LOGIC_BLK_PER_ZONE) {
270 int zone_index;
271
272 zone_index = phys_block / MAX_PHYS_BLK_PER_ZONE;
273 block_address += zone_index * MAX_LOGIC_BLK_PER_ZONE;
274 ssfdc->logic_block_map[block_address] =
275 (unsigned short)phys_block;
276
277 DEBUG(MTD_DEBUG_LEVEL2,
278 "SSFDC_RO: build_block_map() phys_block=%d,"
279 "logic_block_addr=%d, zone=%d\n",
280 phys_block, block_address, zone_index);
281 }
282 }
283 return 0;
284}
285
286static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
287{
288 struct ssfdcr_record *ssfdc;
289 int cis_sector;
290
291 /* Check for small page NAND flash */
292 if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE)
293 return;
294
295 /* Check for SSDFC format by reading CIS/IDI sector */
296 cis_sector = get_valid_cis_sector(mtd);
297 if (cis_sector == -1)
298 return;
299
300 ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL);
301 if (!ssfdc) {
302 printk(KERN_WARNING
303 "SSFDC_RO: out of memory for data structures\n");
304 return;
305 }
306
307 ssfdc->mbd.mtd = mtd;
308 ssfdc->mbd.devnum = -1;
309 ssfdc->mbd.blksize = SECTOR_SIZE;
310 ssfdc->mbd.tr = tr;
311 ssfdc->mbd.readonly = 1;
312
313 ssfdc->cis_block = cis_sector / (mtd->erasesize >> SECTOR_SHIFT);
314 ssfdc->erase_size = mtd->erasesize;
315 ssfdc->map_len = mtd->size / mtd->erasesize;
316
317 DEBUG(MTD_DEBUG_LEVEL1,
318 "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
319 ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len,
320 (ssfdc->map_len + MAX_PHYS_BLK_PER_ZONE - 1) /
321 MAX_PHYS_BLK_PER_ZONE);
322
323 /* Set geometry */
324 ssfdc->heads = 16;
325 ssfdc->sectors = 32;
326 get_chs( mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors);
327 ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) /
328 ((long)ssfdc->sectors * (long)ssfdc->heads));
329
330 DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
331 ssfdc->cylinders, ssfdc->heads , ssfdc->sectors,
332 (long)ssfdc->cylinders * (long)ssfdc->heads *
333 (long)ssfdc->sectors );
334
335 ssfdc->mbd.size = (long)ssfdc->heads * (long)ssfdc->cylinders *
336 (long)ssfdc->sectors;
337
338 /* Allocate logical block map */
339 ssfdc->logic_block_map = kmalloc( sizeof(ssfdc->logic_block_map[0]) *
340 ssfdc->map_len, GFP_KERNEL);
341 if (!ssfdc->logic_block_map) {
342 printk(KERN_WARNING
343 "SSFDC_RO: out of memory for data structures\n");
344 goto out_err;
345 }
346 memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) *
347 ssfdc->map_len);
348
349 /* Build logical block map */
350 if (build_logical_block_map(ssfdc) < 0)
351 goto out_err;
352
353 /* Register device + partitions */
354 if (add_mtd_blktrans_dev(&ssfdc->mbd))
355 goto out_err;
356
357 printk(KERN_INFO "SSFDC_RO: Found ssfdc%c on mtd%d (%s)\n",
358 ssfdc->mbd.devnum + 'a', mtd->index, mtd->name);
359 return;
360
361out_err:
362 kfree(ssfdc->logic_block_map);
363 kfree(ssfdc);
364}
365
366static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev)
367{
368 struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
369
370 DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: remove_dev (i=%d)\n", dev->devnum);
371
372 del_mtd_blktrans_dev(dev);
373 kfree(ssfdc->logic_block_map);
374 kfree(ssfdc);
375}
376
377static int ssfdcr_readsect(struct mtd_blktrans_dev *dev,
378 unsigned long logic_sect_no, char *buf)
379{
380 struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
381 int sectors_per_block, offset, block_address;
382
383 sectors_per_block = ssfdc->erase_size >> SECTOR_SHIFT;
384 offset = (int)(logic_sect_no % sectors_per_block);
385 block_address = (int)(logic_sect_no / sectors_per_block);
386
387 DEBUG(MTD_DEBUG_LEVEL3,
388 "SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d,"
389 " block_addr=%d\n", logic_sect_no, sectors_per_block, offset,
390 block_address);
391
392 if (block_address >= ssfdc->map_len)
393 BUG();
394
395 block_address = ssfdc->logic_block_map[block_address];
396
397 DEBUG(MTD_DEBUG_LEVEL3,
398 "SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n",
399 block_address);
400
401 if (block_address < 0xffff) {
402 unsigned long sect_no;
403
404 sect_no = (unsigned long)block_address * sectors_per_block +
405 offset;
406
407 DEBUG(MTD_DEBUG_LEVEL3,
408 "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n",
409 sect_no);
410
411 if (read_physical_sector( ssfdc->mbd.mtd, buf, sect_no ) < 0)
412 return -EIO;
413 } else {
414 memset(buf, 0xff, SECTOR_SIZE);
415 }
416
417 return 0;
418}
419
420static int ssfdcr_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
421{
422 struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev;
423
424 DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n",
425 ssfdc->cylinders, ssfdc->heads, ssfdc->sectors);
426
427 geo->heads = ssfdc->heads;
428 geo->sectors = ssfdc->sectors;
429 geo->cylinders = ssfdc->cylinders;
430
431 return 0;
432}
433
434/****************************************************************************
435 *
436 * Module stuff
437 *
438 ****************************************************************************/
439
440static struct mtd_blktrans_ops ssfdcr_tr = {
441 .name = "ssfdc",
442 .major = SSFDCR_MAJOR,
443 .part_bits = SSFDCR_PARTN_BITS,
444 .getgeo = ssfdcr_getgeo,
445 .readsect = ssfdcr_readsect,
446 .add_mtd = ssfdcr_add_mtd,
447 .remove_dev = ssfdcr_remove_dev,
448 .owner = THIS_MODULE,
449};
450
451static int __init init_ssfdcr(void)
452{
453 printk(KERN_INFO "SSFDC read-only Flash Translation layer\n");
454
455 return register_mtd_blktrans(&ssfdcr_tr);
456}
457
458static void __exit cleanup_ssfdcr(void)
459{
460 deregister_mtd_blktrans(&ssfdcr_tr);
461}
462
463module_init(init_ssfdcr);
464module_exit(cleanup_ssfdcr);
465
466MODULE_LICENSE("GPL");
467MODULE_AUTHOR("Claudio Lanconelli <lanconelli.claudio@eptar.com>");
468MODULE_DESCRIPTION("Flash Translation Layer for read-only SSFDC SmartMedia card");