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