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