- Andries Brouwer: final isofs pieces.
[davej-history.git] / drivers / mtd / pmc551.c
blobab9049356adeb09b8f97ed061bcf2576136974f3
1 /*
2 * $Id: pmc551.c,v 1.11 2000/11/23 13:40:12 dwmw2 Exp $
4 * PMC551 PCI Mezzanine Ram Device
6 * Author:
7 * Mark Ferrell <mferrell@mvista.com>
8 * Copyright 1999,2000 Nortel Networks
10 * License:
11 * As part of this driver was derrived from the slram.c driver it falls
12 * under the same license, which is GNU General Public License v2
14 * Description:
15 * This driver is intended to support the PMC551 PCI Ram device from
16 * Ramix Inc. The PMC551 is a PMC Mezzanine module for cPCI embeded
17 * systems. The device contains a single SROM that initally programs the
18 * V370PDC chipset onboard the device, and various banks of DRAM/SDRAM
19 * onboard. This driver implements this PCI Ram device as an MTD (Memory
20 * Technologies Device) so that it can be used to hold a filesystem, or
21 * for added swap space in embeded systems. Since the memory on this
22 * board isn't as fast as main memory we do not try to hook it into main
23 * memeory as that would simply reduce performance on the system. Using
24 * it as a block device allows us to use it as high speed swap or for a
25 * high speed disk device of some sort. Which becomes very usefull on
26 * diskless systems in the embeded market I might add.
28 * Notes:
29 * Due to what I assume is more buggy SROM, the 64M PMC551 I have
30 * available claims that all 4 of it's DRAM banks have 64M of ram
31 * configured (making a grand total of 256M onboard). This is slightly
32 * annoying since the BAR0 size reflects the aperture size, not the dram
33 * size, and the V370PDC supplies no other method for memory size
34 * discovery. This problem is mostly only relivant when compiled as a
35 * module, as the unloading of the module with an aperture size smaller
36 * then the ram will cause the driver to detect the onboard memory size
37 * to be equal to the aperture size when the module is reloaded. Soooo,
38 * to help, the module supports an msize option to allow the
39 * specification of the onboard memory, and an asize option, to allow the
40 * specification of the aperture size. The aperture must be equal to or
41 * less then the memory size, the driver will correct this if you screw
42 * it up. This problem is not relivant for compiled in drivers as
43 * compiled in drivers only init once.
45 * Credits:
46 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the initial
47 * example code of how to initialize this device and for help with
48 * questions I had concerning operation of the device.
50 * Most of the MTD code for this driver was originally written for the
51 * slram.o module in the MTD drivers package written by David Hinds
52 * <dhinds@allegro.stanford.edu> which allows the mapping of system
53 * memory into an mtd device. Since the PMC551 memory module is
54 * accessed in the same fashion as system memory, the slram.c code
55 * became a very nice fit to the needs of this driver. All we added was
56 * PCI detection/initialization to the driver and automaticly figure out
57 * the size via the PCI detection.o, later changes by Corey Minyard
58 * settup the card to utilize a 1M sliding apature.
60 * Corey Minyard <minyard@nortelnetworks.com>
61 * * Modified driver to utilize a sliding apature instead of mapping all
62 * memory into kernel space which turned out to be very wastefull.
63 * * Located a bug in the SROM's initialization sequence that made the
64 * memory unusable, added a fix to code to touch up the DRAM some.
66 * Bugs/FIXME's:
67 * * MUST fix the init function to not spin on a register
68 * waiting for it to set .. this does not safely handle busted devices
69 * that never reset the register correctly which will cause the system to
70 * hang w/ a reboot beeing the only chance at recover.
73 #include <linux/config.h>
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <asm/uaccess.h>
77 #include <linux/types.h>
78 #include <linux/sched.h>
79 #include <linux/init.h>
80 #include <linux/ptrace.h>
81 #include <linux/malloc.h>
82 #include <linux/string.h>
83 #include <linux/timer.h>
84 #include <linux/major.h>
85 #include <linux/fs.h>
86 #include <linux/ioctl.h>
87 #include <asm/io.h>
88 #include <asm/system.h>
89 #include <asm/segment.h>
90 #include <stdarg.h>
91 #include <linux/pci.h>
93 #ifndef CONFIG_PCI
94 #error Enable PCI in your kernel config
95 #endif
97 #include <linux/mtd/mtd.h>
98 #include <linux/mtd/pmc551.h>
99 #include <linux/mtd/compatmac.h>
101 #if LINUX_VERSION_CODE > 0x20300
102 #define PCI_BASE_ADDRESS(dev) (dev->resource[0].start)
103 #else
104 #define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
105 #endif
107 static struct mtd_info *pmc551list = NULL;
109 static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr)
111 struct mypriv *priv = mtd->priv;
112 u32 start_addr_highbits;
113 u32 end_addr_highbits;
114 u32 start_addr_lowbits;
115 u32 end_addr_lowbits;
116 unsigned long end;
118 end = instr->addr + instr->len;
120 /* Is it too much memory? The second check find if we wrap around
121 past the end of a u32. */
122 if ((end > mtd->size) || (end < instr->addr)) {
123 return -EINVAL;
126 start_addr_highbits = instr->addr & PMC551_ADDR_HIGH_MASK;
127 end_addr_highbits = end & PMC551_ADDR_HIGH_MASK;
128 start_addr_lowbits = instr->addr & PMC551_ADDR_LOW_MASK;
129 end_addr_lowbits = end & PMC551_ADDR_LOW_MASK;
131 pci_write_config_dword ( priv->dev,
132 PMC551_PCI_MEM_MAP0,
133 (priv->mem_map0_base_val
134 | start_addr_highbits));
135 if (start_addr_highbits == end_addr_highbits) {
136 /* The whole thing fits within one access, so just one shot
137 will do it. */
138 memset(priv->start + start_addr_lowbits,
139 0xff,
140 instr->len);
141 } else {
142 /* We have to do multiple writes to get all the data
143 written. */
144 memset(priv->start + start_addr_lowbits,
145 0xff,
146 priv->aperture_size - start_addr_lowbits);
147 start_addr_highbits += priv->aperture_size;
148 while (start_addr_highbits != end_addr_highbits) {
149 pci_write_config_dword ( priv->dev,
150 PMC551_PCI_MEM_MAP0,
151 (priv->mem_map0_base_val
152 | start_addr_highbits));
153 memset(priv->start,
154 0xff,
155 priv->aperture_size);
156 start_addr_highbits += priv->aperture_size;
158 priv->curr_mem_map0_val = (priv->mem_map0_base_val
159 | start_addr_highbits);
160 pci_write_config_dword ( priv->dev,
161 PMC551_PCI_MEM_MAP0,
162 priv->curr_mem_map0_val);
163 memset(priv->start,
164 0xff,
165 end_addr_lowbits);
168 instr->state = MTD_ERASE_DONE;
170 if (instr->callback) {
171 (*(instr->callback))(instr);
174 return 0;
178 static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr)
182 static int pmc551_read (struct mtd_info *mtd,
183 loff_t from,
184 size_t len,
185 size_t *retlen,
186 u_char *buf)
188 struct mypriv *priv = (struct mypriv *)mtd->priv;
189 u32 start_addr_highbits;
190 u32 end_addr_highbits;
191 u32 start_addr_lowbits;
192 u32 end_addr_lowbits;
193 unsigned long end;
194 u_char *copyto = buf;
197 /* Is it past the end? */
198 if (from > mtd->size) {
199 return -EINVAL;
202 end = from + len;
203 start_addr_highbits = from & PMC551_ADDR_HIGH_MASK;
204 end_addr_highbits = end & PMC551_ADDR_HIGH_MASK;
205 start_addr_lowbits = from & PMC551_ADDR_LOW_MASK;
206 end_addr_lowbits = end & PMC551_ADDR_LOW_MASK;
209 /* Only rewrite the first value if it doesn't match our current
210 values. Most operations are on the same page as the previous
211 value, so this is a pretty good optimization. */
212 if (priv->curr_mem_map0_val !=
213 (priv->mem_map0_base_val | start_addr_highbits)) {
214 priv->curr_mem_map0_val = (priv->mem_map0_base_val
215 | start_addr_highbits);
216 pci_write_config_dword ( priv->dev,
217 PMC551_PCI_MEM_MAP0,
218 priv->curr_mem_map0_val);
221 if (start_addr_highbits == end_addr_highbits) {
222 /* The whole thing fits within one access, so just one shot
223 will do it. */
224 memcpy(copyto,
225 priv->start + start_addr_lowbits,
226 len);
227 copyto += len;
228 } else {
229 /* We have to do multiple writes to get all the data
230 written. */
231 memcpy(copyto,
232 priv->start + start_addr_lowbits,
233 priv->aperture_size - start_addr_lowbits);
234 copyto += priv->aperture_size - start_addr_lowbits;
235 start_addr_highbits += priv->aperture_size;
236 while (start_addr_highbits != end_addr_highbits) {
237 pci_write_config_dword ( priv->dev,
238 PMC551_PCI_MEM_MAP0,
239 (priv->mem_map0_base_val
240 | start_addr_highbits));
241 memcpy(copyto,
242 priv->start,
243 priv->aperture_size);
244 copyto += priv->aperture_size;
245 start_addr_highbits += priv->aperture_size;
246 if (start_addr_highbits >= mtd->size) {
247 /* Make sure we have the right value here. */
248 priv->curr_mem_map0_val
249 = (priv->mem_map0_base_val
250 | start_addr_highbits);
251 goto out;
254 priv->curr_mem_map0_val = (priv->mem_map0_base_val
255 | start_addr_highbits);
256 pci_write_config_dword ( priv->dev,
257 PMC551_PCI_MEM_MAP0,
258 priv->curr_mem_map0_val);
259 memcpy(copyto,
260 priv->start,
261 end_addr_lowbits);
262 copyto += end_addr_lowbits;
265 out:
266 *retlen = copyto - buf;
267 return 0;
270 static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
272 struct mypriv *priv = (struct mypriv *)mtd->priv;
273 u32 start_addr_highbits;
274 u32 end_addr_highbits;
275 u32 start_addr_lowbits;
276 u32 end_addr_lowbits;
277 unsigned long end;
278 const u_char *copyfrom = buf;
281 /* Is it past the end? */
282 if (to > mtd->size) {
283 return -EINVAL;
286 end = to + len;
287 start_addr_highbits = to & PMC551_ADDR_HIGH_MASK;
288 end_addr_highbits = end & PMC551_ADDR_HIGH_MASK;
289 start_addr_lowbits = to & PMC551_ADDR_LOW_MASK;
290 end_addr_lowbits = end & PMC551_ADDR_LOW_MASK;
293 /* Only rewrite the first value if it doesn't match our current
294 values. Most operations are on the same page as the previous
295 value, so this is a pretty good optimization. */
296 if (priv->curr_mem_map0_val !=
297 (priv->mem_map0_base_val | start_addr_highbits)) {
298 priv->curr_mem_map0_val = (priv->mem_map0_base_val
299 | start_addr_highbits);
300 pci_write_config_dword ( priv->dev,
301 PMC551_PCI_MEM_MAP0,
302 priv->curr_mem_map0_val);
305 if (start_addr_highbits == end_addr_highbits) {
306 /* The whole thing fits within one access, so just one shot
307 will do it. */
308 memcpy(priv->start + start_addr_lowbits,
309 copyfrom,
310 len);
311 copyfrom += len;
312 } else {
313 /* We have to do multiple writes to get all the data
314 written. */
315 memcpy(priv->start + start_addr_lowbits,
316 copyfrom,
317 priv->aperture_size - start_addr_lowbits);
318 copyfrom += priv->aperture_size - start_addr_lowbits;
319 start_addr_highbits += priv->aperture_size;
320 while (start_addr_highbits != end_addr_highbits) {
321 pci_write_config_dword ( priv->dev,
322 PMC551_PCI_MEM_MAP0,
323 (priv->mem_map0_base_val
324 | start_addr_highbits));
325 memcpy(priv->start,
326 copyfrom,
327 priv->aperture_size);
328 copyfrom += priv->aperture_size;
329 start_addr_highbits += priv->aperture_size;
330 if (start_addr_highbits >= mtd->size) {
331 /* Make sure we have the right value here. */
332 priv->curr_mem_map0_val
333 = (priv->mem_map0_base_val
334 | start_addr_highbits);
335 goto out;
338 priv->curr_mem_map0_val = (priv->mem_map0_base_val
339 | start_addr_highbits);
340 pci_write_config_dword ( priv->dev,
341 PMC551_PCI_MEM_MAP0,
342 priv->curr_mem_map0_val);
343 memcpy(priv->start,
344 copyfrom,
345 end_addr_lowbits);
346 copyfrom += end_addr_lowbits;
349 out:
350 *retlen = copyfrom - buf;
351 return 0;
355 * Fixup routines for the V370PDC
356 * PCI device ID 0x020011b0
358 * This function basicly kick starts the DRAM oboard the card and gets it
359 * ready to be used. Before this is done the device reads VERY erratic, so
360 * much that it can crash the Linux 2.2.x series kernels when a user cat's
361 * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
362 * register. FIXME: stop spinning on registers .. must implement a timeout
363 * mechanism
364 * returns the size of the memory region found.
366 static u32 fixup_pmc551 (struct pci_dev *dev)
368 #ifdef CONFIG_MTD_PMC551_BUGFIX
369 u32 dram_data;
370 #endif
371 u32 size, dcmd, cfg, dtmp;
372 u16 cmd, tmp, i;
373 u8 bcmd, counter;
375 /* Sanity Check */
376 if(!dev) {
377 return -ENODEV;
381 * Attempt to reset the card
382 * FIXME: Stop Spinning registers
384 counter=0;
385 /* unlock registers */
386 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 );
387 /* read in old data */
388 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
389 /* bang the reset line up and down for a few */
390 for(i=0;i<10;i++) {
391 counter=0;
392 bcmd &= ~0x80;
393 while(counter++ < 100) {
394 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
396 counter=0;
397 bcmd |= 0x80;
398 while(counter++ < 100) {
399 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
402 bcmd |= (0x40|0x20);
403 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
406 * Take care and turn off the memory on the device while we
407 * tweak the configurations
409 pci_read_config_word(dev, PCI_COMMAND, &cmd);
410 tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
411 pci_write_config_word(dev, PCI_COMMAND, tmp);
414 * Disable existing aperture before probing memory size
416 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
417 dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN);
418 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
420 * Grab old BAR0 config so that we can figure out memory size
421 * This is another bit of kludge going on. The reason for the
422 * redundancy is I am hoping to retain the original configuration
423 * previously assigned to the card by the BIOS or some previous
424 * fixup routine in the kernel. So we read the old config into cfg,
425 * then write all 1's to the memory space, read back the result into
426 * "size", and then write back all the old config.
428 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg );
429 #ifndef CONFIG_MTD_PMC551_BUGFIX
430 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 );
431 pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size );
432 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
433 size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1;
434 #else
436 * Get the size of the memory by reading all the DRAM size values
437 * and adding them up.
439 * KLUDGE ALERT: the boards we are using have invalid column and
440 * row mux values. We fix them here, but this will break other
441 * memory configurations.
443 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
444 size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
445 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
446 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
447 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
449 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
450 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
451 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
452 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
453 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
455 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
456 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
457 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
458 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
459 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
461 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
462 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
463 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
464 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
465 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
468 * Oops .. something went wrong
470 if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
471 return -ENODEV;
473 #endif /* CONFIG_MTD_PMC551_BUGFIX */
475 if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
476 return -ENODEV;
480 * Precharge Dram
482 pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 );
483 pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf );
486 * Wait untill command has gone through
487 * FIXME: register spinning issue
489 do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
490 if(counter++ > 100)break;
491 } while ( (PCI_COMMAND_IO) & cmd );
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.
500 for ( i = 1; i<=8 ; i++) {
501 pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df);
504 * Make certain command has gone through
505 * FIXME: register spinning issue
507 counter=0;
508 do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
509 if(counter++ > 100)break;
510 } while ( (PCI_COMMAND_IO) & cmd );
513 pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020);
514 pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff);
517 * Wait until command completes
518 * FIXME: register spinning issue
520 counter=0;
521 do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
522 if(counter++ > 100)break;
523 } while ( (PCI_COMMAND_IO) & cmd );
525 pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd);
526 dcmd |= 0x02000000;
527 pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd);
530 * Check to make certain fast back-to-back, if not
531 * then set it so
533 pci_read_config_word( dev, PCI_STATUS, &cmd);
534 if((cmd&PCI_COMMAND_FAST_BACK) == 0) {
535 cmd |= PCI_COMMAND_FAST_BACK;
536 pci_write_config_word( dev, PCI_STATUS, cmd);
540 * Check to make certain the DEVSEL is set correctly, this device
541 * has a tendancy to assert DEVSEL and TRDY when a write is performed
542 * to the memory when memory is read-only
544 if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) {
545 cmd &= ~PCI_STATUS_DEVSEL_MASK;
546 pci_write_config_word( dev, PCI_STATUS, cmd );
549 * Set to be prefetchable and put everything back based on old cfg.
550 * it's possible that the reset of the V370PDC nuked the original
551 * settup
553 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
554 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
557 * Turn PCI memory and I/O bus access back on
559 pci_write_config_word( dev, PCI_COMMAND,
560 PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
561 #ifdef CONFIG_MTD_PMC551_DEBUG
563 * Some screen fun
565 printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n",
566 (size<1024)?size:(size<1048576)?size/1024:size/1024/1024,
567 (size<1024)?'B':(size<1048576)?'K':'M',
568 size, ((dcmd&(0x1<<3)) == 0)?"non-":"",
569 PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
572 * Check to see the state of the memory
574 pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd );
575 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
576 "pmc551: DRAM_BLK0 Size: %d at %d\n"
577 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
578 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
579 (((0x1<<0)&dcmd) == 0)?"Off":"On",
580 PMC551_DRAM_BLK_GET_SIZE(dcmd),
581 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
583 pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd );
584 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
585 "pmc551: DRAM_BLK1 Size: %d at %d\n"
586 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
587 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
588 (((0x1<<0)&dcmd) == 0)?"Off":"On",
589 PMC551_DRAM_BLK_GET_SIZE(dcmd),
590 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
592 pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd );
593 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
594 "pmc551: DRAM_BLK2 Size: %d at %d\n"
595 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
596 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
597 (((0x1<<0)&dcmd) == 0)?"Off":"On",
598 PMC551_DRAM_BLK_GET_SIZE(dcmd),
599 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
601 pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd );
602 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
603 "pmc551: DRAM_BLK3 Size: %d at %d\n"
604 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
605 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
606 (((0x1<<0)&dcmd) == 0)?"Off":"On",
607 PMC551_DRAM_BLK_GET_SIZE(dcmd),
608 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
610 pci_read_config_word( dev, PCI_COMMAND, &cmd );
611 printk( KERN_DEBUG "pmc551: Memory Access %s\n",
612 (((0x1<<1)&cmd) == 0)?"off":"on" );
613 printk( KERN_DEBUG "pmc551: I/O Access %s\n",
614 (((0x1<<0)&cmd) == 0)?"off":"on" );
616 pci_read_config_word( dev, PCI_STATUS, &cmd );
617 printk( KERN_DEBUG "pmc551: Devsel %s\n",
618 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast":
619 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium":
620 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" );
622 printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
623 ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" );
625 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
626 printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n"
627 "pmc551: System Control Register is %slocked to PCI access\n"
628 "pmc551: System Control Register is %slocked to EEPROM access\n",
629 (bcmd&0x1)?"software":"hardware",
630 (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un");
631 #endif
632 return size;
636 * Kernel version specific module stuffages
638 #if LINUX_VERSION_CODE < 0x20211
639 #ifdef MODULE
640 #define init_pmc551 init_module
641 #define cleanup_pmc551 cleanup_module
642 #endif
643 #define __exit
644 #endif
646 #if defined(MODULE)
647 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
648 MODULE_DESCRIPTION(PMC551_VERSION);
649 MODULE_PARM(msize, "i");
650 MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, ect.. [32M-1024M]");
651 MODULE_PARM(asize, "i");
652 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]");
653 #endif
655 * Stuff these outside the ifdef so as to not bust compiled in driver support
657 static int msize=0;
658 #if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
659 static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE
660 #else
661 static int asize=0;
662 #endif
665 * PMC551 Card Initialization
667 int __init init_pmc551(void)
669 struct pci_dev *PCI_Device = NULL;
670 struct mypriv *priv;
671 int count, found=0;
672 struct mtd_info *mtd;
673 u32 length = 0;
675 if(msize) {
676 if (msize < 6 || msize > 11 ) {
677 printk(KERN_NOTICE "pmc551: Invalid memory size\n");
678 return -ENODEV;
680 msize = (512*1024)<<msize;
683 if(asize) {
684 if (asize < 1 || asize > 11 ) {
685 printk(KERN_NOTICE "pmc551: Invalid aperture size\n");
686 return -ENODEV;
688 asize = (512*1024)<<asize;
691 printk(KERN_INFO PMC551_VERSION);
693 if(!pci_present()) {
694 printk(KERN_NOTICE "pmc551: PCI not enabled.\n");
695 return -ENODEV;
699 * PCU-bus chipset probe.
701 for( count = 0; count < MAX_MTD_DEVICES; count++ ) {
703 if ( (PCI_Device = pci_find_device( PCI_VENDOR_ID_V3_SEMI,
704 PCI_DEVICE_ID_V3_SEMI_V370PDC, PCI_Device ) ) == NULL) {
705 break;
708 printk(KERN_NOTICE "pmc551: Found PCI V370PDC IRQ:%d\n",
709 PCI_Device->irq);
712 * The PMC551 device acts VERY wierd if you don't init it
713 * first. i.e. it will not correctly report devsel. If for
714 * some reason the sdram is in a wrote-protected state the
715 * device will DEVSEL when it is written to causing problems
716 * with the oldproc.c driver in
717 * some kernels (2.2.*)
719 if((length = fixup_pmc551(PCI_Device)) <= 0) {
720 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
721 break;
723 if(msize) {
724 length = msize;
725 printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length);
728 mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
729 if (!mtd) {
730 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n");
731 break;
734 memset(mtd, 0, sizeof(struct mtd_info));
736 priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL);
737 if (!priv) {
738 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n");
739 kfree(mtd);
740 break;
742 memset(priv, 0, sizeof(*priv));
743 mtd->priv = priv;
745 priv->dev = PCI_Device;
746 if(asize) {
747 if(asize > length) {
748 asize=length;
749 printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize);
750 } else {
751 printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize);
753 priv->aperture_size = asize;
754 } else {
755 priv->aperture_size = length;
757 priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device)
758 & PCI_BASE_ADDRESS_MEM_MASK),
759 priv->aperture_size);
762 * Due to the dynamic nature of the code, we need to figure
763 * this out in order to stuff the register to set the proper
764 * aperture size. If you know of an easier way to do this then
765 * PLEASE help yourself.
767 * Not with bloody floating point, you don't. Consider yourself
768 * duly LARTed. dwmw2.
771 u32 size;
772 u16 bits;
773 size = priv->aperture_size>>20;
774 for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1);
775 //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4);
776 priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN
777 | PMC551_PCI_MEM_MAP_ENABLE
778 | size);
779 #ifdef CONFIG_MTD_PMC551_DEBUG
780 printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n",
781 size, size>>4);
782 #endif
784 priv->curr_mem_map0_val = priv->mem_map0_base_val;
786 pci_write_config_dword ( priv->dev,
787 PMC551_PCI_MEM_MAP0,
788 priv->curr_mem_map0_val);
790 mtd->size = length;
791 mtd->flags = (MTD_CLEAR_BITS
792 | MTD_SET_BITS
793 | MTD_WRITEB_WRITEABLE
794 | MTD_VOLATILE);
795 mtd->erase = pmc551_erase;
796 mtd->point = NULL;
797 mtd->unpoint = pmc551_unpoint;
798 mtd->read = pmc551_read;
799 mtd->write = pmc551_write;
800 mtd->module = THIS_MODULE;
801 mtd->type = MTD_RAM;
802 mtd->name = "PMC551 RAM board";
803 mtd->erasesize = 0x10000;
805 if (add_mtd_device(mtd)) {
806 printk(KERN_NOTICE "pmc551: Failed to register new device\n");
807 kfree(mtd->priv);
808 kfree(mtd);
809 break;
811 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
812 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
813 priv->aperture_size/1024/1024,
814 priv->start,
815 priv->start + priv->aperture_size);
816 printk(KERN_NOTICE "Total memory is %d%c\n",
817 (length<1024)?length:
818 (length<1048576)?length/1024:length/1024/1024,
819 (length<1024)?'B':(length<1048576)?'K':'M');
820 priv->nextpmc551 = pmc551list;
821 pmc551list = mtd;
822 found++;
825 if( !pmc551list ) {
826 printk(KERN_NOTICE "pmc551: not detected,\n");
827 return -ENODEV;
828 } else {
829 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
830 return 0;
835 * PMC551 Card Cleanup
837 static void __exit cleanup_pmc551(void)
839 int found=0;
840 struct mtd_info *mtd;
841 struct mypriv *priv;
843 while((mtd=pmc551list)) {
844 priv = (struct mypriv *)mtd->priv;
845 pmc551list = priv->nextpmc551;
847 if(priv->start)
848 iounmap(((struct mypriv *)mtd->priv)->start);
850 kfree (mtd->priv);
851 del_mtd_device(mtd);
852 kfree(mtd);
853 found++;
856 printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
859 #if LINUX_VERSION_CODE >= 0x20211
860 module_init(init_pmc551);
861 module_exit(cleanup_pmc551);
862 #endif