Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PMC551 PCI Mezzanine Ram Device
0004  *
0005  * Author:
0006  *  Mark Ferrell <mferrell@mvista.com>
0007  *  Copyright 1999,2000 Nortel Networks
0008  *
0009  * Description:
0010  *  This driver is intended to support the PMC551 PCI Ram device
0011  *  from Ramix Inc.  The PMC551 is a PMC Mezzanine module for
0012  *  cPCI embedded systems.  The device contains a single SROM
0013  *  that initially programs the V370PDC chipset onboard the
0014  *  device, and various banks of DRAM/SDRAM onboard.  This driver
0015  *  implements this PCI Ram device as an MTD (Memory Technology
0016  *  Device) so that it can be used to hold a file system, or for
0017  *  added swap space in embedded systems.  Since the memory on
0018  *  this board isn't as fast as main memory we do not try to hook
0019  *  it into main memory as that would simply reduce performance
0020  *  on the system.  Using it as a block device allows us to use
0021  *  it as high speed swap or for a high speed disk device of some
0022  *  sort.  Which becomes very useful on diskless systems in the
0023  *  embedded market I might add.
0024  *
0025  * Notes:
0026  *  Due to what I assume is more buggy SROM, the 64M PMC551 I
0027  *  have available claims that all 4 of its DRAM banks have 64MiB
0028  *  of ram configured (making a grand total of 256MiB onboard).
0029  *  This is slightly annoying since the BAR0 size reflects the
0030  *  aperture size, not the dram size, and the V370PDC supplies no
0031  *  other method for memory size discovery.  This problem is
0032  *  mostly only relevant when compiled as a module, as the
0033  *  unloading of the module with an aperture size smaller than
0034  *  the ram will cause the driver to detect the onboard memory
0035  *  size to be equal to the aperture size when the module is
0036  *  reloaded.  Soooo, to help, the module supports an msize
0037  *  option to allow the specification of the onboard memory, and
0038  *  an asize option, to allow the specification of the aperture
0039  *  size.  The aperture must be equal to or less then the memory
0040  *  size, the driver will correct this if you screw it up.  This
0041  *  problem is not relevant for compiled in drivers as compiled
0042  *  in drivers only init once.
0043  *
0044  * Credits:
0045  *  Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
0046  *  initial example code of how to initialize this device and for
0047  *  help with questions I had concerning operation of the device.
0048  *
0049  *  Most of the MTD code for this driver was originally written
0050  *  for the slram.o module in the MTD drivers package which
0051  *  allows the mapping of system memory into an MTD device.
0052  *  Since the PMC551 memory module is accessed in the same
0053  *  fashion as system memory, the slram.c code became a very nice
0054  *  fit to the needs of this driver.  All we added was PCI
0055  *  detection/initialization to the driver and automatically figure
0056  *  out the size via the PCI detection.o, later changes by Corey
0057  *  Minyard set up the card to utilize a 1M sliding apature.
0058  *
0059  *  Corey Minyard <minyard@nortelnetworks.com>
0060  *  * Modified driver to utilize a sliding aperture instead of
0061  *   mapping all memory into kernel space which turned out to
0062  *   be very wasteful.
0063  *  * Located a bug in the SROM's initialization sequence that
0064  *   made the memory unusable, added a fix to code to touch up
0065  *   the DRAM some.
0066  *
0067  * Bugs/FIXMEs:
0068  *  * MUST fix the init function to not spin on a register
0069  *  waiting for it to set .. this does not safely handle busted
0070  *  devices that never reset the register correctly which will
0071  *  cause the system to hang w/ a reboot being the only chance at
0072  *  recover. [sort of fixed, could be better]
0073  *  * Add I2C handling of the SROM so we can read the SROM's information
0074  *  about the aperture size.  This should always accurately reflect the
0075  *  onboard memory size.
0076  *  * Comb the init routine.  It's still a bit cludgy on a few things.
0077  */
0078 
0079 #include <linux/kernel.h>
0080 #include <linux/module.h>
0081 #include <linux/uaccess.h>
0082 #include <linux/types.h>
0083 #include <linux/init.h>
0084 #include <linux/ptrace.h>
0085 #include <linux/slab.h>
0086 #include <linux/string.h>
0087 #include <linux/timer.h>
0088 #include <linux/major.h>
0089 #include <linux/fs.h>
0090 #include <linux/ioctl.h>
0091 #include <asm/io.h>
0092 #include <linux/pci.h>
0093 #include <linux/mtd/mtd.h>
0094 
0095 #define PMC551_VERSION \
0096     "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
0097 
0098 #define PCI_VENDOR_ID_V3_SEMI 0x11b0
0099 #define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
0100 
0101 #define PMC551_PCI_MEM_MAP0 0x50
0102 #define PMC551_PCI_MEM_MAP1 0x54
0103 #define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
0104 #define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
0105 #define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
0106 #define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
0107 
0108 #define PMC551_SDRAM_MA  0x60
0109 #define PMC551_SDRAM_CMD 0x62
0110 #define PMC551_DRAM_CFG  0x64
0111 #define PMC551_SYS_CTRL_REG 0x78
0112 
0113 #define PMC551_DRAM_BLK0 0x68
0114 #define PMC551_DRAM_BLK1 0x6c
0115 #define PMC551_DRAM_BLK2 0x70
0116 #define PMC551_DRAM_BLK3 0x74
0117 #define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f))
0118 #define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
0119 #define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
0120 
0121 struct mypriv {
0122     struct pci_dev *dev;
0123     u_char *start;
0124     u32 base_map0;
0125     u32 curr_map0;
0126     u32 asize;
0127     struct mtd_info *nextpmc551;
0128 };
0129 
0130 static struct mtd_info *pmc551list;
0131 
0132 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
0133             size_t *retlen, void **virt, resource_size_t *phys);
0134 
0135 static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
0136 {
0137     struct mypriv *priv = mtd->priv;
0138     u32 soff_hi;        /* start address offset hi */
0139     u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
0140     unsigned long end;
0141     u_char *ptr;
0142     size_t retlen;
0143 
0144 #ifdef CONFIG_MTD_PMC551_DEBUG
0145     printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
0146         (long)instr->len);
0147 #endif
0148 
0149     end = instr->addr + instr->len - 1;
0150     eoff_hi = end & ~(priv->asize - 1);
0151     soff_hi = instr->addr & ~(priv->asize - 1);
0152     eoff_lo = end & (priv->asize - 1);
0153 
0154     pmc551_point(mtd, instr->addr, instr->len, &retlen,
0155              (void **)&ptr, NULL);
0156 
0157     if (soff_hi == eoff_hi || mtd->size == priv->asize) {
0158         /* The whole thing fits within one access, so just one shot
0159            will do it. */
0160         memset(ptr, 0xff, instr->len);
0161     } else {
0162         /* We have to do multiple writes to get all the data
0163            written. */
0164         while (soff_hi != eoff_hi) {
0165 #ifdef CONFIG_MTD_PMC551_DEBUG
0166             printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
0167                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
0168 #endif
0169             memset(ptr, 0xff, priv->asize);
0170             if (soff_hi + priv->asize >= mtd->size) {
0171                 goto out;
0172             }
0173             soff_hi += priv->asize;
0174             pmc551_point(mtd, (priv->base_map0 | soff_hi),
0175                      priv->asize, &retlen,
0176                      (void **)&ptr, NULL);
0177         }
0178         memset(ptr, 0xff, eoff_lo);
0179     }
0180 
0181       out:
0182 #ifdef CONFIG_MTD_PMC551_DEBUG
0183     printk(KERN_DEBUG "pmc551_erase() done\n");
0184 #endif
0185 
0186     return 0;
0187 }
0188 
0189 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
0190             size_t *retlen, void **virt, resource_size_t *phys)
0191 {
0192     struct mypriv *priv = mtd->priv;
0193     u32 soff_hi;
0194     u32 soff_lo;
0195 
0196 #ifdef CONFIG_MTD_PMC551_DEBUG
0197     printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
0198 #endif
0199 
0200     soff_hi = from & ~(priv->asize - 1);
0201     soff_lo = from & (priv->asize - 1);
0202 
0203     /* Cheap hack optimization */
0204     if (priv->curr_map0 != from) {
0205         pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
0206                     (priv->base_map0 | soff_hi));
0207         priv->curr_map0 = soff_hi;
0208     }
0209 
0210     *virt = priv->start + soff_lo;
0211     *retlen = len;
0212     return 0;
0213 }
0214 
0215 static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
0216 {
0217 #ifdef CONFIG_MTD_PMC551_DEBUG
0218     printk(KERN_DEBUG "pmc551_unpoint()\n");
0219 #endif
0220     return 0;
0221 }
0222 
0223 static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
0224             size_t * retlen, u_char * buf)
0225 {
0226     struct mypriv *priv = mtd->priv;
0227     u32 soff_hi;        /* start address offset hi */
0228     u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
0229     unsigned long end;
0230     u_char *ptr;
0231     u_char *copyto = buf;
0232 
0233 #ifdef CONFIG_MTD_PMC551_DEBUG
0234     printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
0235         (long)from, (long)len, (long)priv->asize);
0236 #endif
0237 
0238     end = from + len - 1;
0239     soff_hi = from & ~(priv->asize - 1);
0240     eoff_hi = end & ~(priv->asize - 1);
0241     eoff_lo = end & (priv->asize - 1);
0242 
0243     pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
0244 
0245     if (soff_hi == eoff_hi) {
0246         /* The whole thing fits within one access, so just one shot
0247            will do it. */
0248         memcpy(copyto, ptr, len);
0249         copyto += len;
0250     } else {
0251         /* We have to do multiple writes to get all the data
0252            written. */
0253         while (soff_hi != eoff_hi) {
0254 #ifdef CONFIG_MTD_PMC551_DEBUG
0255             printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
0256                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
0257 #endif
0258             memcpy(copyto, ptr, priv->asize);
0259             copyto += priv->asize;
0260             if (soff_hi + priv->asize >= mtd->size) {
0261                 goto out;
0262             }
0263             soff_hi += priv->asize;
0264             pmc551_point(mtd, soff_hi, priv->asize, retlen,
0265                      (void **)&ptr, NULL);
0266         }
0267         memcpy(copyto, ptr, eoff_lo);
0268         copyto += eoff_lo;
0269     }
0270 
0271       out:
0272 #ifdef CONFIG_MTD_PMC551_DEBUG
0273     printk(KERN_DEBUG "pmc551_read() done\n");
0274 #endif
0275     *retlen = copyto - buf;
0276     return 0;
0277 }
0278 
0279 static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
0280             size_t * retlen, const u_char * buf)
0281 {
0282     struct mypriv *priv = mtd->priv;
0283     u32 soff_hi;        /* start address offset hi */
0284     u32 eoff_hi, eoff_lo;   /* end address offset hi/lo */
0285     unsigned long end;
0286     u_char *ptr;
0287     const u_char *copyfrom = buf;
0288 
0289 #ifdef CONFIG_MTD_PMC551_DEBUG
0290     printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
0291         (long)to, (long)len, (long)priv->asize);
0292 #endif
0293 
0294     end = to + len - 1;
0295     soff_hi = to & ~(priv->asize - 1);
0296     eoff_hi = end & ~(priv->asize - 1);
0297     eoff_lo = end & (priv->asize - 1);
0298 
0299     pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
0300 
0301     if (soff_hi == eoff_hi) {
0302         /* The whole thing fits within one access, so just one shot
0303            will do it. */
0304         memcpy(ptr, copyfrom, len);
0305         copyfrom += len;
0306     } else {
0307         /* We have to do multiple writes to get all the data
0308            written. */
0309         while (soff_hi != eoff_hi) {
0310 #ifdef CONFIG_MTD_PMC551_DEBUG
0311             printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
0312                 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
0313 #endif
0314             memcpy(ptr, copyfrom, priv->asize);
0315             copyfrom += priv->asize;
0316             if (soff_hi >= mtd->size) {
0317                 goto out;
0318             }
0319             soff_hi += priv->asize;
0320             pmc551_point(mtd, soff_hi, priv->asize, retlen,
0321                      (void **)&ptr, NULL);
0322         }
0323         memcpy(ptr, copyfrom, eoff_lo);
0324         copyfrom += eoff_lo;
0325     }
0326 
0327       out:
0328 #ifdef CONFIG_MTD_PMC551_DEBUG
0329     printk(KERN_DEBUG "pmc551_write() done\n");
0330 #endif
0331     *retlen = copyfrom - buf;
0332     return 0;
0333 }
0334 
0335 /*
0336  * Fixup routines for the V370PDC
0337  * PCI device ID 0x020011b0
0338  *
0339  * This function basically kick starts the DRAM oboard the card and gets it
0340  * ready to be used.  Before this is done the device reads VERY erratic, so
0341  * much that it can crash the Linux 2.2.x series kernels when a user cat's
0342  * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
0343  * register.  FIXME: stop spinning on registers .. must implement a timeout
0344  * mechanism
0345  * returns the size of the memory region found.
0346  */
0347 static int __init fixup_pmc551(struct pci_dev *dev)
0348 {
0349 #ifdef CONFIG_MTD_PMC551_BUGFIX
0350     u32 dram_data;
0351 #endif
0352     u32 size, dcmd, cfg, dtmp;
0353     u16 cmd, tmp, i;
0354     u8 bcmd, counter;
0355 
0356     /* Sanity Check */
0357     if (!dev) {
0358         return -ENODEV;
0359     }
0360 
0361     /*
0362      * Attempt to reset the card
0363      * FIXME: Stop Spinning registers
0364      */
0365     counter = 0;
0366     /* unlock registers */
0367     pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
0368     /* read in old data */
0369     pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
0370     /* bang the reset line up and down for a few */
0371     for (i = 0; i < 10; i++) {
0372         counter = 0;
0373         bcmd &= ~0x80;
0374         while (counter++ < 100) {
0375             pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
0376         }
0377         counter = 0;
0378         bcmd |= 0x80;
0379         while (counter++ < 100) {
0380             pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
0381         }
0382     }
0383     bcmd |= (0x40 | 0x20);
0384     pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
0385 
0386     /*
0387      * Take care and turn off the memory on the device while we
0388      * tweak the configurations
0389      */
0390     pci_read_config_word(dev, PCI_COMMAND, &cmd);
0391     tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
0392     pci_write_config_word(dev, PCI_COMMAND, tmp);
0393 
0394     /*
0395      * Disable existing aperture before probing memory size
0396      */
0397     pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
0398     dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
0399     pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
0400     /*
0401      * Grab old BAR0 config so that we can figure out memory size
0402      * This is another bit of kludge going on.  The reason for the
0403      * redundancy is I am hoping to retain the original configuration
0404      * previously assigned to the card by the BIOS or some previous
0405      * fixup routine in the kernel.  So we read the old config into cfg,
0406      * then write all 1's to the memory space, read back the result into
0407      * "size", and then write back all the old config.
0408      */
0409     pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
0410 #ifndef CONFIG_MTD_PMC551_BUGFIX
0411     pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
0412     pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
0413     size = (size & PCI_BASE_ADDRESS_MEM_MASK);
0414     size &= ~(size - 1);
0415     pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
0416 #else
0417     /*
0418      * Get the size of the memory by reading all the DRAM size values
0419      * and adding them up.
0420      *
0421      * KLUDGE ALERT: the boards we are using have invalid column and
0422      * row mux values.  We fix them here, but this will break other
0423      * memory configurations.
0424      */
0425     pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
0426     size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
0427     dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
0428     dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
0429     pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
0430 
0431     pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
0432     size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
0433     dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
0434     dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
0435     pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
0436 
0437     pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
0438     size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
0439     dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
0440     dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
0441     pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
0442 
0443     pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
0444     size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
0445     dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
0446     dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
0447     pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
0448 
0449     /*
0450      * Oops .. something went wrong
0451      */
0452     if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
0453         return -ENODEV;
0454     }
0455 #endif              /* CONFIG_MTD_PMC551_BUGFIX */
0456 
0457     if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
0458         return -ENODEV;
0459     }
0460 
0461     /*
0462      * Precharge Dram
0463      */
0464     pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
0465     pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
0466 
0467     /*
0468      * Wait until command has gone through
0469      * FIXME: register spinning issue
0470      */
0471     do {
0472         pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
0473         if (counter++ > 100)
0474             break;
0475     } while ((PCI_COMMAND_IO) & cmd);
0476 
0477     /*
0478      * Turn on auto refresh
0479      * The loop is taken directly from Ramix's example code.  I assume that
0480      * this must be held high for some duration of time, but I can find no
0481      * documentation refrencing the reasons why.
0482      */
0483     for (i = 1; i <= 8; i++) {
0484         pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
0485 
0486         /*
0487          * Make certain command has gone through
0488          * FIXME: register spinning issue
0489          */
0490         counter = 0;
0491         do {
0492             pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
0493             if (counter++ > 100)
0494                 break;
0495         } while ((PCI_COMMAND_IO) & cmd);
0496     }
0497 
0498     pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
0499     pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
0500 
0501     /*
0502      * Wait until command completes
0503      * FIXME: register spinning issue
0504      */
0505     counter = 0;
0506     do {
0507         pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
0508         if (counter++ > 100)
0509             break;
0510     } while ((PCI_COMMAND_IO) & cmd);
0511 
0512     pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
0513     dcmd |= 0x02000000;
0514     pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
0515 
0516     /*
0517      * Check to make certain fast back-to-back, if not
0518      * then set it so
0519      */
0520     pci_read_config_word(dev, PCI_STATUS, &cmd);
0521     if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
0522         cmd |= PCI_COMMAND_FAST_BACK;
0523         pci_write_config_word(dev, PCI_STATUS, cmd);
0524     }
0525 
0526     /*
0527      * Check to make certain the DEVSEL is set correctly, this device
0528      * has a tendency to assert DEVSEL and TRDY when a write is performed
0529      * to the memory when memory is read-only
0530      */
0531     if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
0532         cmd &= ~PCI_STATUS_DEVSEL_MASK;
0533         pci_write_config_word(dev, PCI_STATUS, cmd);
0534     }
0535     /*
0536      * Set to be prefetchable and put everything back based on old cfg.
0537      * it's possible that the reset of the V370PDC nuked the original
0538      * setup
0539      */
0540     /*
0541        cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
0542        pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
0543      */
0544 
0545     /*
0546      * Turn PCI memory and I/O bus access back on
0547      */
0548     pci_write_config_word(dev, PCI_COMMAND,
0549                   PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
0550 #ifdef CONFIG_MTD_PMC551_DEBUG
0551     /*
0552      * Some screen fun
0553      */
0554     printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
0555         "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
0556         size >> 10 : size >> 20,
0557         (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
0558         ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
0559         (unsigned long long)pci_resource_start(dev, 0));
0560 
0561     /*
0562      * Check to see the state of the memory
0563      */
0564     pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
0565     printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
0566         "pmc551: DRAM_BLK0 Size: %d at %d\n"
0567         "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
0568         (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
0569         (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
0570         PMC551_DRAM_BLK_GET_SIZE(dcmd),
0571         ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
0572         ((dcmd >> 9) & 0xF));
0573 
0574     pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
0575     printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
0576         "pmc551: DRAM_BLK1 Size: %d at %d\n"
0577         "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
0578         (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
0579         (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
0580         PMC551_DRAM_BLK_GET_SIZE(dcmd),
0581         ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
0582         ((dcmd >> 9) & 0xF));
0583 
0584     pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
0585     printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
0586         "pmc551: DRAM_BLK2 Size: %d at %d\n"
0587         "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
0588         (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
0589         (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
0590         PMC551_DRAM_BLK_GET_SIZE(dcmd),
0591         ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
0592         ((dcmd >> 9) & 0xF));
0593 
0594     pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
0595     printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
0596         "pmc551: DRAM_BLK3 Size: %d at %d\n"
0597         "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
0598         (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
0599         (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
0600         PMC551_DRAM_BLK_GET_SIZE(dcmd),
0601         ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
0602         ((dcmd >> 9) & 0xF));
0603 
0604     pci_read_config_word(dev, PCI_COMMAND, &cmd);
0605     printk(KERN_DEBUG "pmc551: Memory Access %s\n",
0606         (((0x1 << 1) & cmd) == 0) ? "off" : "on");
0607     printk(KERN_DEBUG "pmc551: I/O Access %s\n",
0608         (((0x1 << 0) & cmd) == 0) ? "off" : "on");
0609 
0610     pci_read_config_word(dev, PCI_STATUS, &cmd);
0611     printk(KERN_DEBUG "pmc551: Devsel %s\n",
0612         ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
0613         ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
0614         ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
0615 
0616     printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
0617         ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
0618 
0619     pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
0620     printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
0621         "pmc551: System Control Register is %slocked to PCI access\n"
0622         "pmc551: System Control Register is %slocked to EEPROM access\n",
0623         (bcmd & 0x1) ? "software" : "hardware",
0624         (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
0625 #endif
0626     return size;
0627 }
0628 
0629 /*
0630  * Kernel version specific module stuffages
0631  */
0632 
0633 MODULE_LICENSE("GPL");
0634 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
0635 MODULE_DESCRIPTION(PMC551_VERSION);
0636 
0637 /*
0638  * Stuff these outside the ifdef so as to not bust compiled in driver support
0639  */
0640 static int msize = 0;
0641 static int asize = 0;
0642 
0643 module_param(msize, int, 0);
0644 MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
0645 module_param(asize, int, 0);
0646 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
0647 
0648 /*
0649  * PMC551 Card Initialization
0650  */
0651 static int __init init_pmc551(void)
0652 {
0653     struct pci_dev *PCI_Device = NULL;
0654     struct mypriv *priv;
0655     int found = 0;
0656     struct mtd_info *mtd;
0657     int length = 0;
0658 
0659     if (msize) {
0660         msize = (1 << (ffs(msize) - 1)) << 20;
0661         if (msize > (1 << 30)) {
0662             printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
0663                 msize);
0664             return -EINVAL;
0665         }
0666     }
0667 
0668     if (asize) {
0669         asize = (1 << (ffs(asize) - 1)) << 20;
0670         if (asize > (1 << 30)) {
0671             printk(KERN_NOTICE "pmc551: Invalid aperture size "
0672                 "[%d]\n", asize);
0673             return -EINVAL;
0674         }
0675     }
0676 
0677     printk(KERN_INFO PMC551_VERSION);
0678 
0679     /*
0680      * PCU-bus chipset probe.
0681      */
0682     for (;;) {
0683 
0684         if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
0685                           PCI_DEVICE_ID_V3_SEMI_V370PDC,
0686                           PCI_Device)) == NULL) {
0687             break;
0688         }
0689 
0690         printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
0691             (unsigned long long)pci_resource_start(PCI_Device, 0));
0692 
0693         /*
0694          * The PMC551 device acts VERY weird if you don't init it
0695          * first.  i.e. it will not correctly report devsel.  If for
0696          * some reason the sdram is in a wrote-protected state the
0697          * device will DEVSEL when it is written to causing problems
0698          * with the oldproc.c driver in
0699          * some kernels (2.2.*)
0700          */
0701         if ((length = fixup_pmc551(PCI_Device)) <= 0) {
0702             printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
0703             break;
0704         }
0705 
0706         /*
0707          * This is needed until the driver is capable of reading the
0708          * onboard I2C SROM to discover the "real" memory size.
0709          */
0710         if (msize) {
0711             length = msize;
0712             printk(KERN_NOTICE "pmc551: Using specified memory "
0713                 "size 0x%x\n", length);
0714         } else {
0715             msize = length;
0716         }
0717 
0718         mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
0719         if (!mtd)
0720             break;
0721 
0722         priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
0723         if (!priv) {
0724             kfree(mtd);
0725             break;
0726         }
0727         mtd->priv = priv;
0728         priv->dev = PCI_Device;
0729 
0730         if (asize > length) {
0731             printk(KERN_NOTICE "pmc551: reducing aperture size to "
0732                 "fit %dM\n", length >> 20);
0733             priv->asize = asize = length;
0734         } else if (asize == 0 || asize == length) {
0735             printk(KERN_NOTICE "pmc551: Using existing aperture "
0736                 "size %dM\n", length >> 20);
0737             priv->asize = asize = length;
0738         } else {
0739             printk(KERN_NOTICE "pmc551: Using specified aperture "
0740                 "size %dM\n", asize >> 20);
0741             priv->asize = asize;
0742         }
0743         priv->start = pci_iomap(PCI_Device, 0, priv->asize);
0744 
0745         if (!priv->start) {
0746             printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
0747             kfree(mtd->priv);
0748             kfree(mtd);
0749             break;
0750         }
0751 #ifdef CONFIG_MTD_PMC551_DEBUG
0752         printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
0753             ffs(priv->asize >> 20) - 1);
0754 #endif
0755 
0756         priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
0757                    | PMC551_PCI_MEM_MAP_ENABLE
0758                    | (ffs(priv->asize >> 20) - 1) << 4);
0759         priv->curr_map0 = priv->base_map0;
0760         pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
0761                     priv->curr_map0);
0762 
0763 #ifdef CONFIG_MTD_PMC551_DEBUG
0764         printk(KERN_DEBUG "pmc551: aperture set to %d\n",
0765             (priv->base_map0 & 0xF0) >> 4);
0766 #endif
0767 
0768         mtd->size = msize;
0769         mtd->flags = MTD_CAP_RAM;
0770         mtd->_erase = pmc551_erase;
0771         mtd->_read = pmc551_read;
0772         mtd->_write = pmc551_write;
0773         mtd->_point = pmc551_point;
0774         mtd->_unpoint = pmc551_unpoint;
0775         mtd->type = MTD_RAM;
0776         mtd->name = "PMC551 RAM board";
0777         mtd->erasesize = 0x10000;
0778         mtd->writesize = 1;
0779         mtd->owner = THIS_MODULE;
0780 
0781         if (mtd_device_register(mtd, NULL, 0)) {
0782             printk(KERN_NOTICE "pmc551: Failed to register new device\n");
0783             pci_iounmap(PCI_Device, priv->start);
0784             kfree(mtd->priv);
0785             kfree(mtd);
0786             break;
0787         }
0788 
0789         /* Keep a reference as the mtd_device_register worked */
0790         pci_dev_get(PCI_Device);
0791 
0792         printk(KERN_NOTICE "Registered pmc551 memory device.\n");
0793         printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
0794             priv->asize >> 20,
0795             priv->start, priv->start + priv->asize);
0796         printk(KERN_NOTICE "Total memory is %d%sB\n",
0797             (length < 1024) ? length :
0798             (length < 1048576) ? length >> 10 : length >> 20,
0799             (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
0800         priv->nextpmc551 = pmc551list;
0801         pmc551list = mtd;
0802         found++;
0803     }
0804 
0805     /* Exited early, reference left over */
0806     pci_dev_put(PCI_Device);
0807 
0808     if (!pmc551list) {
0809         printk(KERN_NOTICE "pmc551: not detected\n");
0810         return -ENODEV;
0811     } else {
0812         printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
0813         return 0;
0814     }
0815 }
0816 
0817 /*
0818  * PMC551 Card Cleanup
0819  */
0820 static void __exit cleanup_pmc551(void)
0821 {
0822     int found = 0;
0823     struct mtd_info *mtd;
0824     struct mypriv *priv;
0825 
0826     while ((mtd = pmc551list)) {
0827         priv = mtd->priv;
0828         pmc551list = priv->nextpmc551;
0829 
0830         if (priv->start) {
0831             printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
0832                 "0x%p\n", priv->asize >> 20, priv->start);
0833             pci_iounmap(priv->dev, priv->start);
0834         }
0835         pci_dev_put(priv->dev);
0836 
0837         kfree(mtd->priv);
0838         mtd_device_unregister(mtd);
0839         kfree(mtd);
0840         found++;
0841     }
0842 
0843     printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
0844 }
0845 
0846 module_init(init_pmc551);
0847 module_exit(cleanup_pmc551);