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_0002.c1
-rw-r--r--drivers/mtd/devices/pmc551.c1154
-rw-r--r--drivers/mtd/maps/Kconfig8
-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/mtdcore.c10
-rw-r--r--drivers/mtd/nand/au1550nd.c11
-rw-r--r--drivers/mtd/nand/edb7312.c3
-rw-r--r--drivers/mtd/nand/ndfc.c2
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c7
-rw-r--r--drivers/mtd/ssfdc.c468
31 files changed, 1256 insertions, 723 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_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index a482e8922de1..702ae4cd8691 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -212,6 +212,7 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
212{ 212{
213 mtd->lock = cfi_atmel_lock; 213 mtd->lock = cfi_atmel_lock;
214 mtd->unlock = cfi_atmel_unlock; 214 mtd->unlock = cfi_atmel_unlock;
215 mtd->flags |= MTD_STUPID_LOCK;
215} 216}
216 217
217static struct cfi_fixup cfi_fixup_table[] = { 218static struct cfi_fixup cfi_fixup_table[] = {
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 2c0149708739..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>
@@ -105,74 +105,77 @@
105 105
106static struct mtd_info *pmc551list; 106static struct mtd_info *pmc551list;
107 107
108static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) 108static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
109{ 109{
110 struct mypriv *priv = mtd->priv; 110 struct mypriv *priv = mtd->priv;
111 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 111 u32 soff_hi, soff_lo; /* start address offset hi/lo */
112 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 112 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
113 unsigned long end; 113 unsigned long end;
114 u_char *ptr; 114 u_char *ptr;
115 size_t retlen; 115 size_t retlen;
116 116
117#ifdef CONFIG_MTD_PMC551_DEBUG 117#ifdef CONFIG_MTD_PMC551_DEBUG
118 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);
119#endif 120#endif
120 121
121 end = instr->addr + instr->len - 1; 122 end = instr->addr + instr->len - 1;
122 123
123 /* Is it past the end? */ 124 /* Is it past the end? */
124 if ( end > mtd->size ) { 125 if (end > mtd->size) {
125#ifdef CONFIG_MTD_PMC551_DEBUG 126#ifdef CONFIG_MTD_PMC551_DEBUG
126 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);
127#endif 129#endif
128 return -EINVAL; 130 return -EINVAL;
129 } 131 }
130 132
131 eoff_hi = end & ~(priv->asize - 1); 133 eoff_hi = end & ~(priv->asize - 1);
132 soff_hi = instr->addr & ~(priv->asize - 1); 134 soff_hi = instr->addr & ~(priv->asize - 1);
133 eoff_lo = end & (priv->asize - 1); 135 eoff_lo = end & (priv->asize - 1);
134 soff_lo = instr->addr & (priv->asize - 1); 136 soff_lo = instr->addr & (priv->asize - 1);
135 137
136 pmc551_point (mtd, instr->addr, instr->len, &retlen, &ptr); 138 pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr);
137 139
138 if ( soff_hi == eoff_hi || mtd->size == priv->asize) { 140 if (soff_hi == eoff_hi || mtd->size == priv->asize) {
139 /* The whole thing fits within one access, so just one shot 141 /* The whole thing fits within one access, so just one shot
140 will do it. */ 142 will do it. */
141 memset(ptr, 0xff, instr->len); 143 memset(ptr, 0xff, instr->len);
142 } else { 144 } else {
143 /* We have to do multiple writes to get all the data 145 /* We have to do multiple writes to get all the data
144 written. */ 146 written. */
145 while (soff_hi != eoff_hi) { 147 while (soff_hi != eoff_hi) {
146#ifdef CONFIG_MTD_PMC551_DEBUG 148#ifdef CONFIG_MTD_PMC551_DEBUG
147 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);
148#endif 151#endif
149 memset(ptr, 0xff, priv->asize); 152 memset(ptr, 0xff, priv->asize);
150 if (soff_hi + priv->asize >= mtd->size) { 153 if (soff_hi + priv->asize >= mtd->size) {
151 goto out; 154 goto out;
152 } 155 }
153 soff_hi += priv->asize; 156 soff_hi += priv->asize;
154 pmc551_point (mtd,(priv->base_map0|soff_hi), 157 pmc551_point(mtd, (priv->base_map0 | soff_hi),
155 priv->asize, &retlen, &ptr); 158 priv->asize, &retlen, &ptr);
156 } 159 }
157 memset (ptr, 0xff, eoff_lo); 160 memset(ptr, 0xff, eoff_lo);
158 } 161 }
159 162
160out: 163 out:
161 instr->state = MTD_ERASE_DONE; 164 instr->state = MTD_ERASE_DONE;
162#ifdef CONFIG_MTD_PMC551_DEBUG 165#ifdef CONFIG_MTD_PMC551_DEBUG
163 printk(KERN_DEBUG "pmc551_erase() done\n"); 166 printk(KERN_DEBUG "pmc551_erase() done\n");
164#endif 167#endif
165 168
166 mtd_erase_callback(instr); 169 mtd_erase_callback(instr);
167 return 0; 170 return 0;
168} 171}
169 172
170 173static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
171static 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)
172{ 175{
173 struct mypriv *priv = mtd->priv; 176 struct mypriv *priv = mtd->priv;
174 u32 soff_hi; 177 u32 soff_hi;
175 u32 soff_lo; 178 u32 soff_lo;
176 179
177#ifdef CONFIG_MTD_PMC551_DEBUG 180#ifdef CONFIG_MTD_PMC551_DEBUG
178 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);
@@ -180,18 +183,19 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *
180 183
181 if (from + len > mtd->size) { 184 if (from + len > mtd->size) {
182#ifdef CONFIG_MTD_PMC551_DEBUG 185#ifdef CONFIG_MTD_PMC551_DEBUG
183 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);
184#endif 188#endif
185 return -EINVAL; 189 return -EINVAL;
186 } 190 }
187 191
188 soff_hi = from & ~(priv->asize - 1); 192 soff_hi = from & ~(priv->asize - 1);
189 soff_lo = from & (priv->asize - 1); 193 soff_lo = from & (priv->asize - 1);
190 194
191 /* Cheap hack optimization */ 195 /* Cheap hack optimization */
192 if( priv->curr_map0 != from ) { 196 if (priv->curr_map0 != from) {
193 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, 197 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
194 (priv->base_map0 | soff_hi) ); 198 (priv->base_map0 | soff_hi));
195 priv->curr_map0 = soff_hi; 199 priv->curr_map0 = soff_hi;
196 } 200 }
197 201
@@ -200,137 +204,144 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *
200 return 0; 204 return 0;
201} 205}
202 206
203 207static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
204static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 208 size_t len)
205{ 209{
206#ifdef CONFIG_MTD_PMC551_DEBUG 210#ifdef CONFIG_MTD_PMC551_DEBUG
207 printk(KERN_DEBUG "pmc551_unpoint()\n"); 211 printk(KERN_DEBUG "pmc551_unpoint()\n");
208#endif 212#endif
209} 213}
210 214
211 215static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
212static 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)
213{ 217{
214 struct mypriv *priv = mtd->priv; 218 struct mypriv *priv = mtd->priv;
215 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 219 u32 soff_hi, soff_lo; /* start address offset hi/lo */
216 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 220 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
217 unsigned long end; 221 unsigned long end;
218 u_char *ptr; 222 u_char *ptr;
219 u_char *copyto = buf; 223 u_char *copyto = buf;
220 224
221#ifdef CONFIG_MTD_PMC551_DEBUG 225#ifdef CONFIG_MTD_PMC551_DEBUG
222 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);
223#endif 228#endif
224 229
225 end = from + len - 1; 230 end = from + len - 1;
226 231
227 /* Is it past the end? */ 232 /* Is it past the end? */
228 if (end > mtd->size) { 233 if (end > mtd->size) {
229#ifdef CONFIG_MTD_PMC551_DEBUG 234#ifdef CONFIG_MTD_PMC551_DEBUG
230 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);
231#endif 237#endif
232 return -EINVAL; 238 return -EINVAL;
233 } 239 }
234 240
235 soff_hi = from & ~(priv->asize - 1); 241 soff_hi = from & ~(priv->asize - 1);
236 eoff_hi = end & ~(priv->asize - 1); 242 eoff_hi = end & ~(priv->asize - 1);
237 soff_lo = from & (priv->asize - 1); 243 soff_lo = from & (priv->asize - 1);
238 eoff_lo = end & (priv->asize - 1); 244 eoff_lo = end & (priv->asize - 1);
239 245
240 pmc551_point (mtd, from, len, retlen, &ptr); 246 pmc551_point(mtd, from, len, retlen, &ptr);
241 247
242 if (soff_hi == eoff_hi) { 248 if (soff_hi == eoff_hi) {
243 /* The whole thing fits within one access, so just one shot 249 /* The whole thing fits within one access, so just one shot
244 will do it. */ 250 will do it. */
245 memcpy(copyto, ptr, len); 251 memcpy(copyto, ptr, len);
246 copyto += len; 252 copyto += len;
247 } else { 253 } else {
248 /* We have to do multiple writes to get all the data 254 /* We have to do multiple writes to get all the data
249 written. */ 255 written. */
250 while (soff_hi != eoff_hi) { 256 while (soff_hi != eoff_hi) {
251#ifdef CONFIG_MTD_PMC551_DEBUG 257#ifdef CONFIG_MTD_PMC551_DEBUG
252 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);
253#endif 260#endif
254 memcpy(copyto, ptr, priv->asize); 261 memcpy(copyto, ptr, priv->asize);
255 copyto += priv->asize; 262 copyto += priv->asize;
256 if (soff_hi + priv->asize >= mtd->size) { 263 if (soff_hi + priv->asize >= mtd->size) {
257 goto out; 264 goto out;
258 } 265 }
259 soff_hi += priv->asize; 266 soff_hi += priv->asize;
260 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); 267 pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
261 } 268 }
262 memcpy(copyto, ptr, eoff_lo); 269 memcpy(copyto, ptr, eoff_lo);
263 copyto += eoff_lo; 270 copyto += eoff_lo;
264 } 271 }
265 272
266out: 273 out:
267#ifdef CONFIG_MTD_PMC551_DEBUG 274#ifdef CONFIG_MTD_PMC551_DEBUG
268 printk(KERN_DEBUG "pmc551_read() done\n"); 275 printk(KERN_DEBUG "pmc551_read() done\n");
269#endif 276#endif
270 *retlen = copyto - buf; 277 *retlen = copyto - buf;
271 return 0; 278 return 0;
272} 279}
273 280
274static 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)
275{ 283{
276 struct mypriv *priv = mtd->priv; 284 struct mypriv *priv = mtd->priv;
277 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 285 u32 soff_hi, soff_lo; /* start address offset hi/lo */
278 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 286 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
279 unsigned long end; 287 unsigned long end;
280 u_char *ptr; 288 u_char *ptr;
281 const u_char *copyfrom = buf; 289 const u_char *copyfrom = buf;
282
283 290
284#ifdef CONFIG_MTD_PMC551_DEBUG 291#ifdef CONFIG_MTD_PMC551_DEBUG
285 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);
286#endif 294#endif
287 295
288 end = to + len - 1; 296 end = to + len - 1;
289 /* Is it past the end? or did the u32 wrap? */ 297 /* Is it past the end? or did the u32 wrap? */
290 if (end > mtd->size ) { 298 if (end > mtd->size) {
291#ifdef CONFIG_MTD_PMC551_DEBUG 299#ifdef CONFIG_MTD_PMC551_DEBUG
292 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);
293#endif 303#endif
294 return -EINVAL; 304 return -EINVAL;
295 } 305 }
296 306
297 soff_hi = to & ~(priv->asize - 1); 307 soff_hi = to & ~(priv->asize - 1);
298 eoff_hi = end & ~(priv->asize - 1); 308 eoff_hi = end & ~(priv->asize - 1);
299 soff_lo = to & (priv->asize - 1); 309 soff_lo = to & (priv->asize - 1);
300 eoff_lo = end & (priv->asize - 1); 310 eoff_lo = end & (priv->asize - 1);
301 311
302 pmc551_point (mtd, to, len, retlen, &ptr); 312 pmc551_point(mtd, to, len, retlen, &ptr);
303 313
304 if (soff_hi == eoff_hi) { 314 if (soff_hi == eoff_hi) {
305 /* The whole thing fits within one access, so just one shot 315 /* The whole thing fits within one access, so just one shot
306 will do it. */ 316 will do it. */
307 memcpy(ptr, copyfrom, len); 317 memcpy(ptr, copyfrom, len);
308 copyfrom += len; 318 copyfrom += len;
309 } else { 319 } else {
310 /* We have to do multiple writes to get all the data 320 /* We have to do multiple writes to get all the data
311 written. */ 321 written. */
312 while (soff_hi != eoff_hi) { 322 while (soff_hi != eoff_hi) {
313#ifdef CONFIG_MTD_PMC551_DEBUG 323#ifdef CONFIG_MTD_PMC551_DEBUG
314 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);
315#endif 326#endif
316 memcpy(ptr, copyfrom, priv->asize); 327 memcpy(ptr, copyfrom, priv->asize);
317 copyfrom += priv->asize; 328 copyfrom += priv->asize;
318 if (soff_hi >= mtd->size) { 329 if (soff_hi >= mtd->size) {
319 goto out; 330 goto out;
320 } 331 }
321 soff_hi += priv->asize; 332 soff_hi += priv->asize;
322 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); 333 pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
323 } 334 }
324 memcpy(ptr, copyfrom, eoff_lo); 335 memcpy(ptr, copyfrom, eoff_lo);
325 copyfrom += eoff_lo; 336 copyfrom += eoff_lo;
326 } 337 }
327 338
328out: 339 out:
329#ifdef CONFIG_MTD_PMC551_DEBUG 340#ifdef CONFIG_MTD_PMC551_DEBUG
330 printk(KERN_DEBUG "pmc551_write() done\n"); 341 printk(KERN_DEBUG "pmc551_write() done\n");
331#endif 342#endif
332 *retlen = copyfrom - buf; 343 *retlen = copyfrom - buf;
333 return 0; 344 return 0;
334} 345}
335 346
336/* 347/*
@@ -345,58 +356,58 @@ out:
345 * mechanism 356 * mechanism
346 * returns the size of the memory region found. 357 * returns the size of the memory region found.
347 */ 358 */
348static u32 fixup_pmc551 (struct pci_dev *dev) 359static u32 fixup_pmc551(struct pci_dev *dev)
349{ 360{
350#ifdef CONFIG_MTD_PMC551_BUGFIX 361#ifdef CONFIG_MTD_PMC551_BUGFIX
351 u32 dram_data; 362 u32 dram_data;
352#endif 363#endif
353 u32 size, dcmd, cfg, dtmp; 364 u32 size, dcmd, cfg, dtmp;
354 u16 cmd, tmp, i; 365 u16 cmd, tmp, i;
355 u8 bcmd, counter; 366 u8 bcmd, counter;
356 367
357 /* Sanity Check */ 368 /* Sanity Check */
358 if(!dev) { 369 if (!dev) {
359 return -ENODEV; 370 return -ENODEV;
360 } 371 }
361 372
362 /* 373 /*
363 * Attempt to reset the card 374 * Attempt to reset the card
364 * FIXME: Stop Spinning registers 375 * FIXME: Stop Spinning registers
365 */ 376 */
366 counter=0; 377 counter = 0;
367 /* unlock registers */ 378 /* unlock registers */
368 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); 379 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
369 /* read in old data */ 380 /* read in old data */
370 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); 381 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
371 /* bang the reset line up and down for a few */ 382 /* bang the reset line up and down for a few */
372 for(i=0;i<10;i++) { 383 for (i = 0; i < 10; i++) {
373 counter=0; 384 counter = 0;
374 bcmd &= ~0x80; 385 bcmd &= ~0x80;
375 while(counter++ < 100) { 386 while (counter++ < 100) {
376 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 387 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
377 } 388 }
378 counter=0; 389 counter = 0;
379 bcmd |= 0x80; 390 bcmd |= 0x80;
380 while(counter++ < 100) { 391 while (counter++ < 100) {
381 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 392 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
382 } 393 }
383 } 394 }
384 bcmd |= (0x40|0x20); 395 bcmd |= (0x40 | 0x20);
385 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 396 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
386 397
387 /* 398 /*
388 * 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
389 * tweak the configurations 400 * tweak the configurations
390 */ 401 */
391 pci_read_config_word(dev, PCI_COMMAND, &cmd); 402 pci_read_config_word(dev, PCI_COMMAND, &cmd);
392 tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); 403 tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
393 pci_write_config_word(dev, PCI_COMMAND, tmp); 404 pci_write_config_word(dev, PCI_COMMAND, tmp);
394 405
395 /* 406 /*
396 * Disable existing aperture before probing memory size 407 * Disable existing aperture before probing memory size
397 */ 408 */
398 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); 409 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
399 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);
400 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); 411 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
401 /* 412 /*
402 * 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
@@ -407,220 +418,230 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
407 * 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
408 * "size", and then write back all the old config. 419 * "size", and then write back all the old config.
409 */ 420 */
410 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); 421 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
411#ifndef CONFIG_MTD_PMC551_BUGFIX 422#ifndef CONFIG_MTD_PMC551_BUGFIX
412 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); 423 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
413 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); 424 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
414 size = (size&PCI_BASE_ADDRESS_MEM_MASK); 425 size = (size & PCI_BASE_ADDRESS_MEM_MASK);
415 size &= ~(size-1); 426 size &= ~(size - 1);
416 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); 427 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
417#else 428#else
418 /* 429 /*
419 * 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
420 * and adding them up. 431 * and adding them up.
421 * 432 *
422 * KLUDGE ALERT: the boards we are using have invalid column and 433 * KLUDGE ALERT: the boards we are using have invalid column and
423 * 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
424 * memory configurations. 435 * memory configurations.
425 */ 436 */
426 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); 437 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
427 size = PMC551_DRAM_BLK_GET_SIZE(dram_data); 438 size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
428 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 439 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
429 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 440 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
430 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); 441 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
431 442
432 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); 443 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
433 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 444 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
434 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 445 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
435 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 446 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
436 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); 447 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
437 448
438 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); 449 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
439 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 450 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
440 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 451 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
441 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 452 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
442 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); 453 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
443 454
444 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); 455 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
445 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 456 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
446 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 457 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
447 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 458 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
448 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); 459 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
449 460
450 /* 461 /*
451 * Oops .. something went wrong 462 * Oops .. something went wrong
452 */ 463 */
453 if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { 464 if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
454 return -ENODEV; 465 return -ENODEV;
455 } 466 }
456#endif /* CONFIG_MTD_PMC551_BUGFIX */ 467#endif /* CONFIG_MTD_PMC551_BUGFIX */
457 468
458 if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { 469 if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
459 return -ENODEV; 470 return -ENODEV;
460 } 471 }
461 472
462 /* 473 /*
463 * Precharge Dram 474 * Precharge Dram
464 */ 475 */
465 pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); 476 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
466 pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); 477 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
467 478
468 /* 479 /*
469 * Wait until command has gone through 480 * Wait until command has gone through
470 * FIXME: register spinning issue 481 * FIXME: register spinning issue
471 */ 482 */
472 do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); 483 do {
473 if(counter++ > 100)break; 484 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
474 } while ( (PCI_COMMAND_IO) & cmd ); 485 if (counter++ > 100)
475 486 break;
476 /* 487 } while ((PCI_COMMAND_IO) & cmd);
488
489 /*
477 * Turn on auto refresh 490 * Turn on auto refresh
478 * 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
479 * 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
480 * documentation refrencing the reasons why. 493 * documentation refrencing the reasons why.
481 */ 494 */
482 for ( i = 1; i<=8 ; i++) { 495 for (i = 1; i <= 8; i++) {
483 pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); 496 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
484 497
485 /* 498 /*
486 * Make certain command has gone through 499 * Make certain command has gone through
487 * FIXME: register spinning issue 500 * FIXME: register spinning issue
488 */ 501 */
489 counter=0; 502 counter = 0;
490 do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); 503 do {
491 if(counter++ > 100)break; 504 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
492 } while ( (PCI_COMMAND_IO) & cmd ); 505 if (counter++ > 100)
493 } 506 break;
494 507 } while ((PCI_COMMAND_IO) & cmd);
495 pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); 508 }
496 pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); 509
497 510 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
498 /* 511 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
499 * Wait until command completes 512
500 * FIXME: register spinning issue 513 /*
501 */ 514 * Wait until command completes
502 counter=0; 515 * FIXME: register spinning issue
503 do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); 516 */
504 if(counter++ > 100)break; 517 counter = 0;
505 } while ( (PCI_COMMAND_IO) & cmd ); 518 do {
506 519 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
507 pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); 520 if (counter++ > 100)
508 dcmd |= 0x02000000; 521 break;
509 pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); 522 } while ((PCI_COMMAND_IO) & cmd);
510 523
511 /* 524 pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
512 * Check to make certain fast back-to-back, if not 525 dcmd |= 0x02000000;
513 * then set it so 526 pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
514 */ 527
515 pci_read_config_word( dev, PCI_STATUS, &cmd); 528 /*
516 if((cmd&PCI_COMMAND_FAST_BACK) == 0) { 529 * Check to make certain fast back-to-back, if not
517 cmd |= PCI_COMMAND_FAST_BACK; 530 * then set it so
518 pci_write_config_word( dev, PCI_STATUS, cmd); 531 */
519 } 532 pci_read_config_word(dev, PCI_STATUS, &cmd);
520 533 if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
521 /* 534 cmd |= PCI_COMMAND_FAST_BACK;
522 * Check to make certain the DEVSEL is set correctly, this device 535 pci_write_config_word(dev, PCI_STATUS, cmd);
523 * has a tendancy to assert DEVSEL and TRDY when a write is performed 536 }
524 * to the memory when memory is read-only 537
525 */ 538 /*
526 if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { 539 * Check to make certain the DEVSEL is set correctly, this device
527 cmd &= ~PCI_STATUS_DEVSEL_MASK; 540 * has a tendancy to assert DEVSEL and TRDY when a write is performed
528 pci_write_config_word( dev, PCI_STATUS, cmd ); 541 * to the memory when memory is read-only
529 } 542 */
530 /* 543 if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
531 * 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.
532 * 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
533 * setup 550 * setup
534 */ 551 */
552 /*
553 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
554 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
555 */
556
535 /* 557 /*
536 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; 558 * Turn PCI memory and I/O bus access back on
537 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); 559 */
538 */ 560 pci_write_config_word(dev, PCI_COMMAND,
539 561 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
540 /*
541 * Turn PCI memory and I/O bus access back on
542 */
543 pci_write_config_word( dev, PCI_COMMAND,
544 PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
545#ifdef CONFIG_MTD_PMC551_DEBUG 562#ifdef CONFIG_MTD_PMC551_DEBUG
546 /* 563 /*
547 * Some screen fun 564 * Some screen fun
548 */ 565 */
549 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 "
550 (size<1024)?size:(size<1048576)?size>>10:size>>20, 567 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
551 (size<1024)?'B':(size<1048576)?'K':'M', 568 size >> 10 : size >> 20,
552 size, ((dcmd&(0x1<<3)) == 0)?"non-":"", 569 (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
553 (unsigned long long)((dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK)); 570 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
554 571 (unsigned long long)pci_resource_start(dev, 0));
555 /* 572
556 * Check to see the state of the memory 573 /*
557 */ 574 * Check to see the state of the memory
558 pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); 575 */
559 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" 576 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
560 "pmc551: DRAM_BLK0 Size: %d at %d\n" 577 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
561 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", 578 "pmc551: DRAM_BLK0 Size: %d at %d\n"
562 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 579 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
563 (((0x1<<0)&dcmd) == 0)?"Off":"On", 580 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
564 PMC551_DRAM_BLK_GET_SIZE(dcmd), 581 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
565 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 582 PMC551_DRAM_BLK_GET_SIZE(dcmd),
566 583 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
567 pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); 584 ((dcmd >> 9) & 0xF));
568 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" 585
569 "pmc551: DRAM_BLK1 Size: %d at %d\n" 586 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
570 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", 587 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
571 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 588 "pmc551: DRAM_BLK1 Size: %d at %d\n"
572 (((0x1<<0)&dcmd) == 0)?"Off":"On", 589 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
573 PMC551_DRAM_BLK_GET_SIZE(dcmd), 590 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
574 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 591 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
575 592 PMC551_DRAM_BLK_GET_SIZE(dcmd),
576 pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); 593 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
577 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" 594 ((dcmd >> 9) & 0xF));
578 "pmc551: DRAM_BLK2 Size: %d at %d\n" 595
579 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", 596 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
580 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 597 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
581 (((0x1<<0)&dcmd) == 0)?"Off":"On", 598 "pmc551: DRAM_BLK2 Size: %d at %d\n"
582 PMC551_DRAM_BLK_GET_SIZE(dcmd), 599 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
583 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 600 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
584 601 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
585 pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); 602 PMC551_DRAM_BLK_GET_SIZE(dcmd),
586 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" 603 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
587 "pmc551: DRAM_BLK3 Size: %d at %d\n" 604 ((dcmd >> 9) & 0xF));
588 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", 605
589 (((0x1<<1)&dcmd) == 0)?"RW":"RO", 606 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
590 (((0x1<<0)&dcmd) == 0)?"Off":"On", 607 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
591 PMC551_DRAM_BLK_GET_SIZE(dcmd), 608 "pmc551: DRAM_BLK3 Size: %d at %d\n"
592 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); 609 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
593 610 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
594 pci_read_config_word( dev, PCI_COMMAND, &cmd ); 611 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
595 printk( KERN_DEBUG "pmc551: Memory Access %s\n", 612 PMC551_DRAM_BLK_GET_SIZE(dcmd),
596 (((0x1<<1)&cmd) == 0)?"off":"on" ); 613 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
597 printk( KERN_DEBUG "pmc551: I/O Access %s\n", 614 ((dcmd >> 9) & 0xF));
598 (((0x1<<0)&cmd) == 0)?"off":"on" ); 615
599 616 pci_read_config_word(dev, PCI_COMMAND, &cmd);
600 pci_read_config_word( dev, PCI_STATUS, &cmd ); 617 printk(KERN_DEBUG "pmc551: Memory Access %s\n",
601 printk( KERN_DEBUG "pmc551: Devsel %s\n", 618 (((0x1 << 1) & cmd) == 0) ? "off" : "on");
602 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": 619 printk(KERN_DEBUG "pmc551: I/O Access %s\n",
603 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": 620 (((0x1 << 0) & cmd) == 0) ? "off" : "on");
604 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); 621
605 622 pci_read_config_word(dev, PCI_STATUS, &cmd);
606 printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", 623 printk(KERN_DEBUG "pmc551: Devsel %s\n",
607 ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); 624 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
608 625 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
609 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); 626 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
610 printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" 627
611 "pmc551: System Control Register is %slocked to PCI access\n" 628 printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
612 "pmc551: System Control Register is %slocked to EEPROM access\n", 629 ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
613 (bcmd&0x1)?"software":"hardware", 630
614 (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");
615#endif 637#endif
616 return size; 638 return size;
617} 639}
618 640
619/* 641/*
620 * Kernel version specific module stuffages 642 * Kernel version specific module stuffages
621 */ 643 */
622 644
623
624MODULE_LICENSE("GPL"); 645MODULE_LICENSE("GPL");
625MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>"); 646MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
626MODULE_DESCRIPTION(PMC551_VERSION); 647MODULE_DESCRIPTION(PMC551_VERSION);
@@ -628,11 +649,11 @@ MODULE_DESCRIPTION(PMC551_VERSION);
628/* 649/*
629 * 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
630 */ 651 */
631static int msize=0; 652static int msize = 0;
632#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) 653#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
633static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE 654static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE
634#else 655#else
635static int asize=0; 656static int asize = 0;
636#endif 657#endif
637 658
638module_param(msize, int, 0); 659module_param(msize, int, 0);
@@ -645,164 +666,174 @@ MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
645 */ 666 */
646static int __init init_pmc551(void) 667static int __init init_pmc551(void)
647{ 668{
648 struct pci_dev *PCI_Device = NULL; 669 struct pci_dev *PCI_Device = NULL;
649 struct mypriv *priv; 670 struct mypriv *priv;
650 int count, found=0; 671 int count, found = 0;
651 struct mtd_info *mtd; 672 struct mtd_info *mtd;
652 u32 length = 0; 673 u32 length = 0;
653 674
654 if(msize) { 675 if (msize) {
655 msize = (1 << (ffs(msize) - 1))<<20; 676 msize = (1 << (ffs(msize) - 1)) << 20;
656 if (msize > (1<<30)) { 677 if (msize > (1 << 30)) {
657 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", msize); 678 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
679 msize);
658 return -EINVAL; 680 return -EINVAL;
659 } 681 }
660 } 682 }
661 683
662 if(asize) { 684 if (asize) {
663 asize = (1 << (ffs(asize) - 1))<<20; 685 asize = (1 << (ffs(asize) - 1)) << 20;
664 if (asize > (1<<30) ) { 686 if (asize > (1 << 30)) {
665 printk(KERN_NOTICE "pmc551: Invalid aperture size [%d]\n", asize); 687 printk(KERN_NOTICE "pmc551: Invalid aperture size "
688 "[%d]\n", asize);
666 return -EINVAL; 689 return -EINVAL;
667 } 690 }
668 } 691 }
669 692
670 printk(KERN_INFO PMC551_VERSION); 693 printk(KERN_INFO PMC551_VERSION);
671 694
672 /* 695 /*
673 * PCU-bus chipset probe. 696 * PCU-bus chipset probe.
674 */ 697 */
675 for( count = 0; count < MAX_MTD_DEVICES; count++ ) { 698 for (count = 0; count < MAX_MTD_DEVICES; count++) {
676 699
677 if ((PCI_Device = pci_find_device(PCI_VENDOR_ID_V3_SEMI, 700 if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
678 PCI_DEVICE_ID_V3_SEMI_V370PDC, 701 PCI_DEVICE_ID_V3_SEMI_V370PDC,
679 PCI_Device ) ) == NULL) { 702 PCI_Device)) == NULL) {
680 break; 703 break;
681 } 704 }
682 705
683 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", 706 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
684 (unsigned long long)PCI_Device->resource[0].start); 707 (unsigned long long)pci_resource_start(PCI_Device, 0));
685 708
686 /* 709 /*
687 * 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
688 * first. i.e. it will not correctly report devsel. If for 711 * first. i.e. it will not correctly report devsel. If for
689 * some reason the sdram is in a wrote-protected state the 712 * some reason the sdram is in a wrote-protected state the
690 * device will DEVSEL when it is written to causing problems 713 * device will DEVSEL when it is written to causing problems
691 * with the oldproc.c driver in 714 * with the oldproc.c driver in
692 * some kernels (2.2.*) 715 * some kernels (2.2.*)
693 */ 716 */
694 if((length = fixup_pmc551(PCI_Device)) <= 0) { 717 if ((length = fixup_pmc551(PCI_Device)) <= 0) {
695 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); 718 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
696 break; 719 break;
697 } 720 }
698 721
699 /* 722 /*
700 * This is needed until the driver is capable of reading the 723 * This is needed until the driver is capable of reading the
701 * onboard I2C SROM to discover the "real" memory size. 724 * onboard I2C SROM to discover the "real" memory size.
702 */ 725 */
703 if(msize) { 726 if (msize) {
704 length = msize; 727 length = msize;
705 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);
706 } else { 730 } else {
707 msize = length; 731 msize = length;
708 } 732 }
709 733
710 mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 734 mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
711 if (!mtd) { 735 if (!mtd) {
712 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); 736 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
713 break; 737 "device.\n");
714 } 738 break;
715 739 }
716 memset(mtd, 0, sizeof(struct mtd_info)); 740
717 741 priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
718 priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); 742 if (!priv) {
719 if (!priv) { 743 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
720 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); 744 "device.\n");
721 kfree(mtd); 745 kfree(mtd);
722 break; 746 break;
723 } 747 }
724 memset(priv, 0, sizeof(*priv)); 748 mtd->priv = priv;
725 mtd->priv = priv; 749 priv->dev = PCI_Device;
726 priv->dev = PCI_Device; 750
727 751 if (asize > length) {
728 if(asize > length) { 752 printk(KERN_NOTICE "pmc551: reducing aperture size to "
729 printk(KERN_NOTICE "pmc551: reducing aperture size to fit %dM\n",length>>20); 753 "fit %dM\n", length >> 20);
730 priv->asize = asize = length; 754 priv->asize = asize = length;
731 } else if (asize == 0 || asize == length) { 755 } else if (asize == 0 || asize == length) {
732 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);
733 priv->asize = asize = length; 758 priv->asize = asize = length;
734 } else { 759 } else {
735 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);
736 priv->asize = asize; 762 priv->asize = asize;
737 } 763 }
738 priv->start = ioremap(((PCI_Device->resource[0].start) 764 priv->start = pci_iomap(PCI_Device, 0, priv->asize);
739 & PCI_BASE_ADDRESS_MEM_MASK),
740 priv->asize);
741 765
742 if (!priv->start) { 766 if (!priv->start) {
743 printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); 767 printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
744 kfree(mtd->priv); 768 kfree(mtd->priv);
745 kfree(mtd); 769 kfree(mtd);
746 break; 770 break;
747 } 771 }
748
749#ifdef CONFIG_MTD_PMC551_DEBUG 772#ifdef CONFIG_MTD_PMC551_DEBUG
750 printk( KERN_DEBUG "pmc551: setting aperture to %d\n", 773 printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
751 ffs(priv->asize>>20)-1); 774 ffs(priv->asize >> 20) - 1);
752#endif 775#endif
753 776
754 priv->base_map0 = ( PMC551_PCI_MEM_MAP_REG_EN 777 priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
755 | PMC551_PCI_MEM_MAP_ENABLE 778 | PMC551_PCI_MEM_MAP_ENABLE
756 | (ffs(priv->asize>>20)-1)<<4 ); 779 | (ffs(priv->asize >> 20) - 1) << 4);
757 priv->curr_map0 = priv->base_map0; 780 priv->curr_map0 = priv->base_map0;
758 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, 781 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
759 priv->curr_map0 ); 782 priv->curr_map0);
760 783
761#ifdef CONFIG_MTD_PMC551_DEBUG 784#ifdef CONFIG_MTD_PMC551_DEBUG
762 printk( KERN_DEBUG "pmc551: aperture set to %d\n", 785 printk(KERN_DEBUG "pmc551: aperture set to %d\n",
763 (priv->base_map0 & 0xF0)>>4 ); 786 (priv->base_map0 & 0xF0) >> 4);
764#endif 787#endif
765 788
766 mtd->size = msize; 789 mtd->size = msize;
767 mtd->flags = MTD_CAP_RAM; 790 mtd->flags = MTD_CAP_RAM;
768 mtd->erase = pmc551_erase; 791 mtd->erase = pmc551_erase;
769 mtd->read = pmc551_read; 792 mtd->read = pmc551_read;
770 mtd->write = pmc551_write; 793 mtd->write = pmc551_write;
771 mtd->point = pmc551_point; 794 mtd->point = pmc551_point;
772 mtd->unpoint = pmc551_unpoint; 795 mtd->unpoint = pmc551_unpoint;
773 mtd->type = MTD_RAM; 796 mtd->type = MTD_RAM;
774 mtd->name = "PMC551 RAM board"; 797 mtd->name = "PMC551 RAM board";
775 mtd->erasesize = 0x10000; 798 mtd->erasesize = 0x10000;
776 mtd->writesize = 1; 799 mtd->writesize = 1;
777 mtd->owner = THIS_MODULE; 800 mtd->owner = THIS_MODULE;
778 801
779 if (add_mtd_device(mtd)) { 802 if (add_mtd_device(mtd)) {
780 printk(KERN_NOTICE "pmc551: Failed to register new device\n"); 803 printk(KERN_NOTICE "pmc551: Failed to register new "
781 iounmap(priv->start); 804 "device\n");
782 kfree(mtd->priv); 805 pci_iounmap(PCI_Device, priv->start);
783 kfree(mtd); 806 kfree(mtd->priv);
784 break; 807 kfree(mtd);
785 } 808 break;
786 printk(KERN_NOTICE "Registered pmc551 memory device.\n"); 809 }
787 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", 810
788 priv->asize>>20, 811 /* Keep a reference as the add_mtd_device worked */
789 priv->start, 812 pci_dev_get(PCI_Device);
790 priv->start + priv->asize); 813
791 printk(KERN_NOTICE "Total memory is %d%c\n", 814 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
792 (length<1024)?length: 815 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
793 (length<1048576)?length>>10:length>>20, 816 priv->asize >> 20,
794 (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');
795 priv->nextpmc551 = pmc551list; 822 priv->nextpmc551 = pmc551list;
796 pmc551list = mtd; 823 pmc551list = mtd;
797 found++; 824 found++;
798 } 825 }
826
827 /* Exited early, reference left over */
828 if (PCI_Device)
829 pci_dev_put(PCI_Device);
799 830
800 if( !pmc551list ) { 831 if (!pmc551list) {
801 printk(KERN_NOTICE "pmc551: not detected\n"); 832 printk(KERN_NOTICE "pmc551: not detected\n");
802 return -ENODEV; 833 return -ENODEV;
803 } else { 834 } else {
804 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); 835 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
805 return 0; 836 return 0;
806 } 837 }
807} 838}
808 839
@@ -811,23 +842,24 @@ static int __init init_pmc551(void)
811 */ 842 */
812static void __exit cleanup_pmc551(void) 843static void __exit cleanup_pmc551(void)
813{ 844{
814 int found=0; 845 int found = 0;
815 struct mtd_info *mtd; 846 struct mtd_info *mtd;
816 struct mypriv *priv; 847 struct mypriv *priv;
817 848
818 while((mtd=pmc551list)) { 849 while ((mtd = pmc551list)) {
819 priv = mtd->priv; 850 priv = mtd->priv;
820 pmc551list = priv->nextpmc551; 851 pmc551list = priv->nextpmc551;
821 852
822 if(priv->start) { 853 if (priv->start) {
823 printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n", 854 printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
824 priv->asize>>20, priv->start); 855 "0x%p\n", priv->asize >> 20, priv->start);
825 iounmap (priv->start); 856 pci_iounmap(priv->dev, priv->start);
826 } 857 }
858 pci_dev_put(priv->dev);
827 859
828 kfree (mtd->priv); 860 kfree(mtd->priv);
829 del_mtd_device (mtd); 861 del_mtd_device(mtd);
830 kfree (mtd); 862 kfree(mtd);
831 found++; 863 found++;
832 } 864 }
833 865
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 64d1b6a6c920..24747bdc3e19 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -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/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/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/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/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");