0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
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;
0139 u32 eoff_hi, eoff_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
0159
0160 memset(ptr, 0xff, instr->len);
0161 } else {
0162
0163
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
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;
0228 u32 eoff_hi, eoff_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
0247
0248 memcpy(copyto, ptr, len);
0249 copyto += len;
0250 } else {
0251
0252
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;
0284 u32 eoff_hi, eoff_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
0303
0304 memcpy(ptr, copyfrom, len);
0305 copyfrom += len;
0306 } else {
0307
0308
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
0337
0338
0339
0340
0341
0342
0343
0344
0345
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
0357 if (!dev) {
0358 return -ENODEV;
0359 }
0360
0361
0362
0363
0364
0365 counter = 0;
0366
0367 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
0368
0369 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
0370
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
0388
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
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
0402
0403
0404
0405
0406
0407
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
0419
0420
0421
0422
0423
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
0451
0452 if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
0453 return -ENODEV;
0454 }
0455 #endif
0456
0457 if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
0458 return -ENODEV;
0459 }
0460
0461
0462
0463
0464 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
0465 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
0466
0467
0468
0469
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
0479
0480
0481
0482
0483 for (i = 1; i <= 8; i++) {
0484 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
0485
0486
0487
0488
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
0503
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
0518
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
0528
0529
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
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548 pci_write_config_word(dev, PCI_COMMAND,
0549 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
0550 #ifdef CONFIG_MTD_PMC551_DEBUG
0551
0552
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
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
0631
0632
0633 MODULE_LICENSE("GPL");
0634 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
0635 MODULE_DESCRIPTION(PMC551_VERSION);
0636
0637
0638
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
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
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
0695
0696
0697
0698
0699
0700
0701 if ((length = fixup_pmc551(PCI_Device)) <= 0) {
0702 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
0703 break;
0704 }
0705
0706
0707
0708
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
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
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
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);