Merge git://git.infradead.org/mtd-2.6
[pandora-kernel.git] / drivers / mtd / devices / pmc551.c
1 /*
2  * PMC551 PCI Mezzanine Ram Device
3  *
4  * Author:
5  *      Mark Ferrell <mferrell@mvista.com>
6  *      Copyright 1999,2000 Nortel Networks
7  *
8  * License:
9  *      As part of this driver was derived from the slram.c driver it
10  *      falls under the same license, which is GNU General Public
11  *      License v2
12  *
13  * Description:
14  *      This driver is intended to support the PMC551 PCI Ram device
15  *      from Ramix Inc.  The PMC551 is a PMC Mezzanine module for
16  *      cPCI embedded systems.  The device contains a single SROM
17  *      that initially programs the V370PDC chipset onboard the
18  *      device, and various banks of DRAM/SDRAM onboard.  This driver
19  *      implements this PCI Ram device as an MTD (Memory Technology
20  *      Device) so that it can be used to hold a file system, or for
21  *      added swap space in embedded systems.  Since the memory on
22  *      this board isn't as fast as main memory we do not try to hook
23  *      it into main memory as that would simply reduce performance
24  *      on the system.  Using it as a block device allows us to use
25  *      it as high speed swap or for a high speed disk device of some
26  *      sort.  Which becomes very useful on diskless systems in the
27  *      embedded market I might add.
28  *
29  * Notes:
30  *      Due to what I assume is more buggy SROM, the 64M PMC551 I
31  *      have available claims that all 4 of its DRAM banks have 64MiB
32  *      of ram configured (making a grand total of 256MiB onboard).
33  *      This is slightly annoying since the BAR0 size reflects the
34  *      aperture size, not the dram size, and the V370PDC supplies no
35  *      other method for memory size discovery.  This problem is
36  *      mostly only relevant when compiled as a module, as the
37  *      unloading of the module with an aperture size smaller than
38  *      the ram will cause the driver to detect the onboard memory
39  *      size to be equal to the aperture size when the module is
40  *      reloaded.  Soooo, to help, the module supports an msize
41  *      option to allow the specification of the onboard memory, and
42  *      an asize option, to allow the specification of the aperture
43  *      size.  The aperture must be equal to or less then the memory
44  *      size, the driver will correct this if you screw it up.  This
45  *      problem is not relevant for compiled in drivers as compiled
46  *      in drivers only init once.
47  *
48  * Credits:
49  *      Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
50  *      initial example code of how to initialize this device and for
51  *      help with questions I had concerning operation of the device.
52  *
53  *      Most of the MTD code for this driver was originally written
54  *      for the slram.o module in the MTD drivers package which
55  *      allows the mapping of system memory into an MTD device.
56  *      Since the PMC551 memory module is accessed in the same
57  *      fashion as system memory, the slram.c code became a very nice
58  *      fit to the needs of this driver.  All we added was PCI
59  *      detection/initialization to the driver and automatically figure
60  *      out the size via the PCI detection.o, later changes by Corey
61  *      Minyard set up the card to utilize a 1M sliding apature.
62  *
63  *      Corey Minyard <minyard@nortelnetworks.com>
64  *      * Modified driver to utilize a sliding aperture instead of
65  *       mapping all memory into kernel space which turned out to
66  *       be very wasteful.
67  *      * Located a bug in the SROM's initialization sequence that
68  *       made the memory unusable, added a fix to code to touch up
69  *       the DRAM some.
70  *
71  * Bugs/FIXMEs:
72  *      * MUST fix the init function to not spin on a register
73  *      waiting for it to set .. this does not safely handle busted
74  *      devices that never reset the register correctly which will
75  *      cause the system to hang w/ a reboot being the only chance at
76  *      recover. [sort of fixed, could be better]
77  *      * Add I2C handling of the SROM so we can read the SROM's information
78  *      about the aperture size.  This should always accurately reflect the
79  *      onboard memory size.
80  *      * Comb the init routine.  It's still a bit cludgy on a few things.
81  */
82
83 #include <linux/kernel.h>
84 #include <linux/module.h>
85 #include <asm/uaccess.h>
86 #include <linux/types.h>
87 #include <linux/init.h>
88 #include <linux/ptrace.h>
89 #include <linux/slab.h>
90 #include <linux/string.h>
91 #include <linux/timer.h>
92 #include <linux/major.h>
93 #include <linux/fs.h>
94 #include <linux/ioctl.h>
95 #include <asm/io.h>
96 #include <asm/system.h>
97 #include <linux/pci.h>
98
99 #include <linux/mtd/mtd.h>
100 #include <linux/mtd/pmc551.h>
101 #include <linux/mtd/compatmac.h>
102
103 static struct mtd_info *pmc551list;
104
105 static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
106 {
107         struct mypriv *priv = mtd->priv;
108         u32 soff_hi, soff_lo;   /* start address offset hi/lo */
109         u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
110         unsigned long end;
111         u_char *ptr;
112         size_t retlen;
113
114 #ifdef CONFIG_MTD_PMC551_DEBUG
115         printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
116                 (long)instr->len);
117 #endif
118
119         end = instr->addr + instr->len - 1;
120
121         /* Is it past the end? */
122         if (end > mtd->size) {
123 #ifdef CONFIG_MTD_PMC551_DEBUG
124                 printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n",
125                         (long)end, (long)mtd->size);
126 #endif
127                 return -EINVAL;
128         }
129
130         eoff_hi = end & ~(priv->asize - 1);
131         soff_hi = instr->addr & ~(priv->asize - 1);
132         eoff_lo = end & (priv->asize - 1);
133         soff_lo = instr->addr & (priv->asize - 1);
134
135         pmc551_point(mtd, instr->addr, instr->len, &retlen,
136                      (void **)&ptr, NULL);
137
138         if (soff_hi == eoff_hi || mtd->size == priv->asize) {
139                 /* The whole thing fits within one access, so just one shot
140                    will do it. */
141                 memset(ptr, 0xff, instr->len);
142         } else {
143                 /* We have to do multiple writes to get all the data
144                    written. */
145                 while (soff_hi != eoff_hi) {
146 #ifdef CONFIG_MTD_PMC551_DEBUG
147                         printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
148                                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
149 #endif
150                         memset(ptr, 0xff, priv->asize);
151                         if (soff_hi + priv->asize >= mtd->size) {
152                                 goto out;
153                         }
154                         soff_hi += priv->asize;
155                         pmc551_point(mtd, (priv->base_map0 | soff_hi),
156                                      priv->asize, &retlen,
157                                      (void **)&ptr, NULL);
158                 }
159                 memset(ptr, 0xff, eoff_lo);
160         }
161
162       out:
163         instr->state = MTD_ERASE_DONE;
164 #ifdef CONFIG_MTD_PMC551_DEBUG
165         printk(KERN_DEBUG "pmc551_erase() done\n");
166 #endif
167
168         mtd_erase_callback(instr);
169         return 0;
170 }
171
172 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
173                         size_t *retlen, void **virt, resource_size_t *phys)
174 {
175         struct mypriv *priv = mtd->priv;
176         u32 soff_hi;
177         u32 soff_lo;
178
179 #ifdef CONFIG_MTD_PMC551_DEBUG
180         printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
181 #endif
182
183         if (from + len > mtd->size) {
184 #ifdef CONFIG_MTD_PMC551_DEBUG
185                 printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n",
186                         (long)from + len, (long)mtd->size);
187 #endif
188                 return -EINVAL;
189         }
190
191         /* can we return a physical address with this driver? */
192         if (phys)
193                 return -EINVAL;
194
195         soff_hi = from & ~(priv->asize - 1);
196         soff_lo = from & (priv->asize - 1);
197
198         /* Cheap hack optimization */
199         if (priv->curr_map0 != from) {
200                 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
201                                         (priv->base_map0 | soff_hi));
202                 priv->curr_map0 = soff_hi;
203         }
204
205         *virt = priv->start + soff_lo;
206         *retlen = len;
207         return 0;
208 }
209
210 static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
211 {
212 #ifdef CONFIG_MTD_PMC551_DEBUG
213         printk(KERN_DEBUG "pmc551_unpoint()\n");
214 #endif
215 }
216
217 static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
218                         size_t * retlen, u_char * buf)
219 {
220         struct mypriv *priv = mtd->priv;
221         u32 soff_hi, soff_lo;   /* start address offset hi/lo */
222         u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
223         unsigned long end;
224         u_char *ptr;
225         u_char *copyto = buf;
226
227 #ifdef CONFIG_MTD_PMC551_DEBUG
228         printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
229                 (long)from, (long)len, (long)priv->asize);
230 #endif
231
232         end = from + len - 1;
233
234         /* Is it past the end? */
235         if (end > mtd->size) {
236 #ifdef CONFIG_MTD_PMC551_DEBUG
237                 printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n",
238                         (long)end, (long)mtd->size);
239 #endif
240                 return -EINVAL;
241         }
242
243         soff_hi = from & ~(priv->asize - 1);
244         eoff_hi = end & ~(priv->asize - 1);
245         soff_lo = from & (priv->asize - 1);
246         eoff_lo = end & (priv->asize - 1);
247
248         pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
249
250         if (soff_hi == eoff_hi) {
251                 /* The whole thing fits within one access, so just one shot
252                    will do it. */
253                 memcpy(copyto, ptr, len);
254                 copyto += len;
255         } else {
256                 /* We have to do multiple writes to get all the data
257                    written. */
258                 while (soff_hi != eoff_hi) {
259 #ifdef CONFIG_MTD_PMC551_DEBUG
260                         printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
261                                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
262 #endif
263                         memcpy(copyto, ptr, priv->asize);
264                         copyto += priv->asize;
265                         if (soff_hi + priv->asize >= mtd->size) {
266                                 goto out;
267                         }
268                         soff_hi += priv->asize;
269                         pmc551_point(mtd, soff_hi, priv->asize, retlen,
270                                      (void **)&ptr, NULL);
271                 }
272                 memcpy(copyto, ptr, eoff_lo);
273                 copyto += eoff_lo;
274         }
275
276       out:
277 #ifdef CONFIG_MTD_PMC551_DEBUG
278         printk(KERN_DEBUG "pmc551_read() done\n");
279 #endif
280         *retlen = copyto - buf;
281         return 0;
282 }
283
284 static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
285                         size_t * retlen, const u_char * buf)
286 {
287         struct mypriv *priv = mtd->priv;
288         u32 soff_hi, soff_lo;   /* start address offset hi/lo */
289         u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
290         unsigned long end;
291         u_char *ptr;
292         const u_char *copyfrom = buf;
293
294 #ifdef CONFIG_MTD_PMC551_DEBUG
295         printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
296                 (long)to, (long)len, (long)priv->asize);
297 #endif
298
299         end = to + len - 1;
300         /* Is it past the end?  or did the u32 wrap? */
301         if (end > mtd->size) {
302 #ifdef CONFIG_MTD_PMC551_DEBUG
303                 printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, "
304                         "size: %ld, to: %ld)\n", (long)end, (long)mtd->size,
305                         (long)to);
306 #endif
307                 return -EINVAL;
308         }
309
310         soff_hi = to & ~(priv->asize - 1);
311         eoff_hi = end & ~(priv->asize - 1);
312         soff_lo = to & (priv->asize - 1);
313         eoff_lo = end & (priv->asize - 1);
314
315         pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
316
317         if (soff_hi == eoff_hi) {
318                 /* The whole thing fits within one access, so just one shot
319                    will do it. */
320                 memcpy(ptr, copyfrom, len);
321                 copyfrom += len;
322         } else {
323                 /* We have to do multiple writes to get all the data
324                    written. */
325                 while (soff_hi != eoff_hi) {
326 #ifdef CONFIG_MTD_PMC551_DEBUG
327                         printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
328                                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
329 #endif
330                         memcpy(ptr, copyfrom, priv->asize);
331                         copyfrom += priv->asize;
332                         if (soff_hi >= mtd->size) {
333                                 goto out;
334                         }
335                         soff_hi += priv->asize;
336                         pmc551_point(mtd, soff_hi, priv->asize, retlen,
337                                      (void **)&ptr, NULL);
338                 }
339                 memcpy(ptr, copyfrom, eoff_lo);
340                 copyfrom += eoff_lo;
341         }
342
343       out:
344 #ifdef CONFIG_MTD_PMC551_DEBUG
345         printk(KERN_DEBUG "pmc551_write() done\n");
346 #endif
347         *retlen = copyfrom - buf;
348         return 0;
349 }
350
351 /*
352  * Fixup routines for the V370PDC
353  * PCI device ID 0x020011b0
354  *
355  * This function basicly kick starts the DRAM oboard the card and gets it
356  * ready to be used.  Before this is done the device reads VERY erratic, so
357  * much that it can crash the Linux 2.2.x series kernels when a user cat's
358  * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
359  * register.  FIXME: stop spinning on registers .. must implement a timeout
360  * mechanism
361  * returns the size of the memory region found.
362  */
363 static u32 fixup_pmc551(struct pci_dev *dev)
364 {
365 #ifdef CONFIG_MTD_PMC551_BUGFIX
366         u32 dram_data;
367 #endif
368         u32 size, dcmd, cfg, dtmp;
369         u16 cmd, tmp, i;
370         u8 bcmd, counter;
371
372         /* Sanity Check */
373         if (!dev) {
374                 return -ENODEV;
375         }
376
377         /*
378          * Attempt to reset the card
379          * FIXME: Stop Spinning registers
380          */
381         counter = 0;
382         /* unlock registers */
383         pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
384         /* read in old data */
385         pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
386         /* bang the reset line up and down for a few */
387         for (i = 0; i < 10; i++) {
388                 counter = 0;
389                 bcmd &= ~0x80;
390                 while (counter++ < 100) {
391                         pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
392                 }
393                 counter = 0;
394                 bcmd |= 0x80;
395                 while (counter++ < 100) {
396                         pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
397                 }
398         }
399         bcmd |= (0x40 | 0x20);
400         pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
401
402         /*
403          * Take care and turn off the memory on the device while we
404          * tweak the configurations
405          */
406         pci_read_config_word(dev, PCI_COMMAND, &cmd);
407         tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
408         pci_write_config_word(dev, PCI_COMMAND, tmp);
409
410         /*
411          * Disable existing aperture before probing memory size
412          */
413         pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
414         dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
415         pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
416         /*
417          * Grab old BAR0 config so that we can figure out memory size
418          * This is another bit of kludge going on.  The reason for the
419          * redundancy is I am hoping to retain the original configuration
420          * previously assigned to the card by the BIOS or some previous
421          * fixup routine in the kernel.  So we read the old config into cfg,
422          * then write all 1's to the memory space, read back the result into
423          * "size", and then write back all the old config.
424          */
425         pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
426 #ifndef CONFIG_MTD_PMC551_BUGFIX
427         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
428         pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
429         size = (size & PCI_BASE_ADDRESS_MEM_MASK);
430         size &= ~(size - 1);
431         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
432 #else
433         /*
434          * Get the size of the memory by reading all the DRAM size values
435          * and adding them up.
436          *
437          * KLUDGE ALERT: the boards we are using have invalid column and
438          * row mux values.  We fix them here, but this will break other
439          * memory configurations.
440          */
441         pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
442         size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
443         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
444         dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
445         pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
446
447         pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
448         size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
449         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
450         dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
451         pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
452
453         pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
454         size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
455         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
456         dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
457         pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
458
459         pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
460         size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
461         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
462         dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
463         pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
464
465         /*
466          * Oops .. something went wrong
467          */
468         if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
469                 return -ENODEV;
470         }
471 #endif                          /* CONFIG_MTD_PMC551_BUGFIX */
472
473         if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
474                 return -ENODEV;
475         }
476
477         /*
478          * Precharge Dram
479          */
480         pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
481         pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
482
483         /*
484          * Wait until command has gone through
485          * FIXME: register spinning issue
486          */
487         do {
488                 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
489                 if (counter++ > 100)
490                         break;
491         } while ((PCI_COMMAND_IO) & cmd);
492
493         /*
494          * Turn on auto refresh
495          * The loop is taken directly from Ramix's example code.  I assume that
496          * this must be held high for some duration of time, but I can find no
497          * documentation refrencing the reasons why.
498          */
499         for (i = 1; i <= 8; i++) {
500                 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
501
502                 /*
503                  * Make certain command has gone through
504                  * FIXME: register spinning issue
505                  */
506                 counter = 0;
507                 do {
508                         pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
509                         if (counter++ > 100)
510                                 break;
511                 } while ((PCI_COMMAND_IO) & cmd);
512         }
513
514         pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
515         pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
516
517         /*
518          * Wait until command completes
519          * FIXME: register spinning issue
520          */
521         counter = 0;
522         do {
523                 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
524                 if (counter++ > 100)
525                         break;
526         } while ((PCI_COMMAND_IO) & cmd);
527
528         pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
529         dcmd |= 0x02000000;
530         pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
531
532         /*
533          * Check to make certain fast back-to-back, if not
534          * then set it so
535          */
536         pci_read_config_word(dev, PCI_STATUS, &cmd);
537         if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
538                 cmd |= PCI_COMMAND_FAST_BACK;
539                 pci_write_config_word(dev, PCI_STATUS, cmd);
540         }
541
542         /*
543          * Check to make certain the DEVSEL is set correctly, this device
544          * has a tendancy to assert DEVSEL and TRDY when a write is performed
545          * to the memory when memory is read-only
546          */
547         if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
548                 cmd &= ~PCI_STATUS_DEVSEL_MASK;
549                 pci_write_config_word(dev, PCI_STATUS, cmd);
550         }
551         /*
552          * Set to be prefetchable and put everything back based on old cfg.
553          * it's possible that the reset of the V370PDC nuked the original
554          * setup
555          */
556         /*
557            cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
558            pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
559          */
560
561         /*
562          * Turn PCI memory and I/O bus access back on
563          */
564         pci_write_config_word(dev, PCI_COMMAND,
565                               PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
566 #ifdef CONFIG_MTD_PMC551_DEBUG
567         /*
568          * Some screen fun
569          */
570         printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
571                 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
572                 size >> 10 : size >> 20,
573                 (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
574                 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
575                 (unsigned long long)pci_resource_start(dev, 0));
576
577         /*
578          * Check to see the state of the memory
579          */
580         pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
581         printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
582                 "pmc551: DRAM_BLK0 Size: %d at %d\n"
583                 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
584                 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
585                 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
586                 PMC551_DRAM_BLK_GET_SIZE(dcmd),
587                 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
588                 ((dcmd >> 9) & 0xF));
589
590         pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
591         printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
592                 "pmc551: DRAM_BLK1 Size: %d at %d\n"
593                 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
594                 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
595                 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
596                 PMC551_DRAM_BLK_GET_SIZE(dcmd),
597                 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
598                 ((dcmd >> 9) & 0xF));
599
600         pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
601         printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
602                 "pmc551: DRAM_BLK2 Size: %d at %d\n"
603                 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
604                 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
605                 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
606                 PMC551_DRAM_BLK_GET_SIZE(dcmd),
607                 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
608                 ((dcmd >> 9) & 0xF));
609
610         pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
611         printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
612                 "pmc551: DRAM_BLK3 Size: %d at %d\n"
613                 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
614                 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
615                 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
616                 PMC551_DRAM_BLK_GET_SIZE(dcmd),
617                 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
618                 ((dcmd >> 9) & 0xF));
619
620         pci_read_config_word(dev, PCI_COMMAND, &cmd);
621         printk(KERN_DEBUG "pmc551: Memory Access %s\n",
622                 (((0x1 << 1) & cmd) == 0) ? "off" : "on");
623         printk(KERN_DEBUG "pmc551: I/O Access %s\n",
624                 (((0x1 << 0) & cmd) == 0) ? "off" : "on");
625
626         pci_read_config_word(dev, PCI_STATUS, &cmd);
627         printk(KERN_DEBUG "pmc551: Devsel %s\n",
628                 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
629                 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
630                 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
631
632         printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
633                 ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
634
635         pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
636         printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
637                 "pmc551: System Control Register is %slocked to PCI access\n"
638                 "pmc551: System Control Register is %slocked to EEPROM access\n",
639                 (bcmd & 0x1) ? "software" : "hardware",
640                 (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
641 #endif
642         return size;
643 }
644
645 /*
646  * Kernel version specific module stuffages
647  */
648
649 MODULE_LICENSE("GPL");
650 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
651 MODULE_DESCRIPTION(PMC551_VERSION);
652
653 /*
654  * Stuff these outside the ifdef so as to not bust compiled in driver support
655  */
656 static int msize = 0;
657 static int asize = 0;
658
659 module_param(msize, int, 0);
660 MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
661 module_param(asize, int, 0);
662 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
663
664 /*
665  * PMC551 Card Initialization
666  */
667 static int __init init_pmc551(void)
668 {
669         struct pci_dev *PCI_Device = NULL;
670         struct mypriv *priv;
671         int found = 0;
672         struct mtd_info *mtd;
673         u32 length = 0;
674
675         if (msize) {
676                 msize = (1 << (ffs(msize) - 1)) << 20;
677                 if (msize > (1 << 30)) {
678                         printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
679                                 msize);
680                         return -EINVAL;
681                 }
682         }
683
684         if (asize) {
685                 asize = (1 << (ffs(asize) - 1)) << 20;
686                 if (asize > (1 << 30)) {
687                         printk(KERN_NOTICE "pmc551: Invalid aperture size "
688                                 "[%d]\n", asize);
689                         return -EINVAL;
690                 }
691         }
692
693         printk(KERN_INFO PMC551_VERSION);
694
695         /*
696          * PCU-bus chipset probe.
697          */
698         for (;;) {
699
700                 if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
701                                                   PCI_DEVICE_ID_V3_SEMI_V370PDC,
702                                                   PCI_Device)) == NULL) {
703                         break;
704                 }
705
706                 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
707                         (unsigned long long)pci_resource_start(PCI_Device, 0));
708
709                 /*
710                  * The PMC551 device acts VERY weird if you don't init it
711                  * first.  i.e. it will not correctly report devsel.  If for
712                  * some reason the sdram is in a wrote-protected state the
713                  * device will DEVSEL when it is written to causing problems
714                  * with the oldproc.c driver in
715                  * some kernels (2.2.*)
716                  */
717                 if ((length = fixup_pmc551(PCI_Device)) <= 0) {
718                         printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
719                         break;
720                 }
721
722                 /*
723                  * This is needed until the driver is capable of reading the
724                  * onboard I2C SROM to discover the "real" memory size.
725                  */
726                 if (msize) {
727                         length = msize;
728                         printk(KERN_NOTICE "pmc551: Using specified memory "
729                                 "size 0x%x\n", length);
730                 } else {
731                         msize = length;
732                 }
733
734                 mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
735                 if (!mtd) {
736                         printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
737                                 "device.\n");
738                         break;
739                 }
740
741                 priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
742                 if (!priv) {
743                         printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
744                                 "device.\n");
745                         kfree(mtd);
746                         break;
747                 }
748                 mtd->priv = priv;
749                 priv->dev = PCI_Device;
750
751                 if (asize > length) {
752                         printk(KERN_NOTICE "pmc551: reducing aperture size to "
753                                 "fit %dM\n", length >> 20);
754                         priv->asize = asize = length;
755                 } else if (asize == 0 || asize == length) {
756                         printk(KERN_NOTICE "pmc551: Using existing aperture "
757                                 "size %dM\n", length >> 20);
758                         priv->asize = asize = length;
759                 } else {
760                         printk(KERN_NOTICE "pmc551: Using specified aperture "
761                                 "size %dM\n", asize >> 20);
762                         priv->asize = asize;
763                 }
764                 priv->start = pci_iomap(PCI_Device, 0, priv->asize);
765
766                 if (!priv->start) {
767                         printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
768                         kfree(mtd->priv);
769                         kfree(mtd);
770                         break;
771                 }
772 #ifdef CONFIG_MTD_PMC551_DEBUG
773                 printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
774                         ffs(priv->asize >> 20) - 1);
775 #endif
776
777                 priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
778                                    | PMC551_PCI_MEM_MAP_ENABLE
779                                    | (ffs(priv->asize >> 20) - 1) << 4);
780                 priv->curr_map0 = priv->base_map0;
781                 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
782                                         priv->curr_map0);
783
784 #ifdef CONFIG_MTD_PMC551_DEBUG
785                 printk(KERN_DEBUG "pmc551: aperture set to %d\n",
786                         (priv->base_map0 & 0xF0) >> 4);
787 #endif
788
789                 mtd->size = msize;
790                 mtd->flags = MTD_CAP_RAM;
791                 mtd->erase = pmc551_erase;
792                 mtd->read = pmc551_read;
793                 mtd->write = pmc551_write;
794                 mtd->point = pmc551_point;
795                 mtd->unpoint = pmc551_unpoint;
796                 mtd->type = MTD_RAM;
797                 mtd->name = "PMC551 RAM board";
798                 mtd->erasesize = 0x10000;
799                 mtd->writesize = 1;
800                 mtd->owner = THIS_MODULE;
801
802                 if (add_mtd_device(mtd)) {
803                         printk(KERN_NOTICE "pmc551: Failed to register new device\n");
804                         pci_iounmap(PCI_Device, priv->start);
805                         kfree(mtd->priv);
806                         kfree(mtd);
807                         break;
808                 }
809
810                 /* Keep a reference as the add_mtd_device worked */
811                 pci_dev_get(PCI_Device);
812
813                 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
814                 printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
815                         priv->asize >> 20,
816                         priv->start, priv->start + priv->asize);
817                 printk(KERN_NOTICE "Total memory is %d%sB\n",
818                         (length < 1024) ? length :
819                         (length < 1048576) ? length >> 10 : length >> 20,
820                         (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
821                 priv->nextpmc551 = pmc551list;
822                 pmc551list = mtd;
823                 found++;
824         }
825
826         /* Exited early, reference left over */
827         if (PCI_Device)
828                 pci_dev_put(PCI_Device);
829
830         if (!pmc551list) {
831                 printk(KERN_NOTICE "pmc551: not detected\n");
832                 return -ENODEV;
833         } else {
834                 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
835                 return 0;
836         }
837 }
838
839 /*
840  * PMC551 Card Cleanup
841  */
842 static void __exit cleanup_pmc551(void)
843 {
844         int found = 0;
845         struct mtd_info *mtd;
846         struct mypriv *priv;
847
848         while ((mtd = pmc551list)) {
849                 priv = mtd->priv;
850                 pmc551list = priv->nextpmc551;
851
852                 if (priv->start) {
853                         printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
854                                 "0x%p\n", priv->asize >> 20, priv->start);
855                         pci_iounmap(priv->dev, priv->start);
856                 }
857                 pci_dev_put(priv->dev);
858
859                 kfree(mtd->priv);
860                 del_mtd_device(mtd);
861                 kfree(mtd);
862                 found++;
863         }
864
865         printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
866 }
867
868 module_init(init_pmc551);
869 module_exit(cleanup_pmc551);