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