Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
0003  *
0004  * Author: Simon Evans <spse@secret.org.uk>
0005  *
0006  * Copyright (C) 2002 Simon Evans
0007  *
0008  * Licence: GPL
0009  *
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/timer.h>
0015 #include <linux/init.h>
0016 #include <asm/io.h>
0017 
0018 #include <pcmcia/cistpl.h>
0019 #include <pcmcia/ds.h>
0020 
0021 #include <linux/mtd/map.h>
0022 #include <linux/mtd/mtd.h>
0023 
0024 #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
0025 
0026 #define DRIVER_DESC "PCMCIA Flash memory card driver"
0027 
0028 /* Size of the PCMCIA address space: 26 bits = 64 MB */
0029 #define MAX_PCMCIA_ADDR 0x4000000
0030 
0031 struct pcmciamtd_dev {
0032     struct pcmcia_device    *p_dev;
0033     void __iomem    *win_base;  /* ioremapped address of PCMCIA window */
0034     unsigned int    win_size;   /* size of window */
0035     unsigned int    offset;     /* offset into card the window currently points at */
0036     struct map_info pcmcia_map;
0037     struct mtd_info *mtd_info;
0038     int     vpp;
0039     char        mtd_name[sizeof(struct cistpl_vers_1_t)];
0040 };
0041 
0042 
0043 /* Module parameters */
0044 
0045 /* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
0046 static int bankwidth = 2;
0047 
0048 /* Speed of memory accesses, in ns */
0049 static int mem_speed;
0050 
0051 /* Force the size of an SRAM card */
0052 static int force_size;
0053 
0054 /* Force Vpp */
0055 static int vpp;
0056 
0057 /* Set Vpp */
0058 static int setvpp;
0059 
0060 /* Force card to be treated as FLASH, ROM or RAM */
0061 static int mem_type;
0062 
0063 MODULE_LICENSE("GPL");
0064 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
0065 MODULE_DESCRIPTION(DRIVER_DESC);
0066 module_param(bankwidth, int, 0);
0067 MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
0068 module_param(mem_speed, int, 0);
0069 MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
0070 module_param(force_size, int, 0);
0071 MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");
0072 module_param(setvpp, int, 0);
0073 MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
0074 module_param(vpp, int, 0);
0075 MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
0076 module_param(mem_type, int, 0);
0077 MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
0078 
0079 
0080 /* read/write{8,16} copy_{from,to} routines with window remapping
0081  * to access whole card
0082  */
0083 static void __iomem *remap_window(struct map_info *map, unsigned long to)
0084 {
0085     struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
0086     struct resource *win = (struct resource *) map->map_priv_2;
0087     unsigned int offset;
0088     int ret;
0089 
0090     if (!pcmcia_dev_present(dev->p_dev)) {
0091         pr_debug("device removed\n");
0092         return NULL;
0093     }
0094 
0095     offset = to & ~(dev->win_size-1);
0096     if (offset != dev->offset) {
0097         pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n",
0098               dev->offset, offset);
0099         ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
0100         if (ret != 0)
0101             return NULL;
0102         dev->offset = offset;
0103     }
0104     return dev->win_base + (to & (dev->win_size-1));
0105 }
0106 
0107 
0108 static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
0109 {
0110     void __iomem *addr;
0111     map_word d = {{0}};
0112 
0113     addr = remap_window(map, ofs);
0114     if(!addr)
0115         return d;
0116 
0117     d.x[0] = readb(addr);
0118     pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]);
0119     return d;
0120 }
0121 
0122 
0123 static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
0124 {
0125     void __iomem *addr;
0126     map_word d = {{0}};
0127 
0128     addr = remap_window(map, ofs);
0129     if(!addr)
0130         return d;
0131 
0132     d.x[0] = readw(addr);
0133     pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]);
0134     return d;
0135 }
0136 
0137 
0138 static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len)
0139 {
0140     struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
0141     unsigned long win_size = dev->win_size;
0142 
0143     pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
0144     while(len) {
0145         int toread = win_size - (from & (win_size-1));
0146         void __iomem *addr;
0147 
0148         if(toread > len)
0149             toread = len;
0150 
0151         addr = remap_window(map, from);
0152         if(!addr)
0153             return;
0154 
0155         pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread);
0156         memcpy_fromio(to, addr, toread);
0157         len -= toread;
0158         to += toread;
0159         from += toread;
0160     }
0161 }
0162 
0163 
0164 static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr)
0165 {
0166     void __iomem *addr = remap_window(map, adr);
0167 
0168     if(!addr)
0169         return;
0170 
0171     pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n", adr, addr, d.x[0]);
0172     writeb(d.x[0], addr);
0173 }
0174 
0175 
0176 static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr)
0177 {
0178     void __iomem *addr = remap_window(map, adr);
0179     if(!addr)
0180         return;
0181 
0182     pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n", adr, addr, d.x[0]);
0183     writew(d.x[0], addr);
0184 }
0185 
0186 
0187 static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len)
0188 {
0189     struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
0190     unsigned long win_size = dev->win_size;
0191 
0192     pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
0193     while(len) {
0194         int towrite = win_size - (to & (win_size-1));
0195         void __iomem *addr;
0196 
0197         if(towrite > len)
0198             towrite = len;
0199 
0200         addr = remap_window(map, to);
0201         if(!addr)
0202             return;
0203 
0204         pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite);
0205         memcpy_toio(addr, from, towrite);
0206         len -= towrite;
0207         to += towrite;
0208         from += towrite;
0209     }
0210 }
0211 
0212 
0213 /* read/write{8,16} copy_{from,to} routines with direct access */
0214 
0215 #define DEV_REMOVED(x)  (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
0216 
0217 static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
0218 {
0219     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0220     map_word d = {{0}};
0221 
0222     if(DEV_REMOVED(map))
0223         return d;
0224 
0225     d.x[0] = readb(win_base + ofs);
0226     pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n",
0227           ofs, win_base + ofs, d.x[0]);
0228     return d;
0229 }
0230 
0231 
0232 static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
0233 {
0234     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0235     map_word d = {{0}};
0236 
0237     if(DEV_REMOVED(map))
0238         return d;
0239 
0240     d.x[0] = readw(win_base + ofs);
0241     pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n",
0242           ofs, win_base + ofs, d.x[0]);
0243     return d;
0244 }
0245 
0246 
0247 static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
0248 {
0249     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0250 
0251     if(DEV_REMOVED(map))
0252         return;
0253 
0254     pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
0255     memcpy_fromio(to, win_base + from, len);
0256 }
0257 
0258 
0259 static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr)
0260 {
0261     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0262 
0263     if(DEV_REMOVED(map))
0264         return;
0265 
0266     pr_debug("adr = 0x%08lx (%p)  data = 0x%02lx\n",
0267           adr, win_base + adr, d.x[0]);
0268     writeb(d.x[0], win_base + adr);
0269 }
0270 
0271 
0272 static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr)
0273 {
0274     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0275 
0276     if(DEV_REMOVED(map))
0277         return;
0278 
0279     pr_debug("adr = 0x%08lx (%p)  data = 0x%04lx\n",
0280           adr, win_base + adr, d.x[0]);
0281     writew(d.x[0], win_base + adr);
0282 }
0283 
0284 
0285 static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
0286 {
0287     void __iomem *win_base = (void __iomem *)map->map_priv_2;
0288 
0289     if(DEV_REMOVED(map))
0290         return;
0291 
0292     pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
0293     memcpy_toio(win_base + to, from, len);
0294 }
0295 
0296 
0297 static DEFINE_MUTEX(pcmcia_vpp_lock);
0298 static int pcmcia_vpp_refcnt;
0299 static void pcmciamtd_set_vpp(struct map_info *map, int on)
0300 {
0301     struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
0302     struct pcmcia_device *link = dev->p_dev;
0303 
0304     pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
0305     mutex_lock(&pcmcia_vpp_lock);
0306     if (on) {
0307         if (++pcmcia_vpp_refcnt == 1)   /* first nested 'on' */
0308             pcmcia_fixup_vpp(link, dev->vpp);
0309     } else {
0310         if (--pcmcia_vpp_refcnt == 0)   /* last nested 'off' */
0311             pcmcia_fixup_vpp(link, 0);
0312     }
0313     mutex_unlock(&pcmcia_vpp_lock);
0314 }
0315 
0316 
0317 static void pcmciamtd_release(struct pcmcia_device *link)
0318 {
0319     struct pcmciamtd_dev *dev = link->priv;
0320 
0321     pr_debug("link = 0x%p\n", link);
0322 
0323     if (link->resource[2]->end) {
0324         if(dev->win_base) {
0325             iounmap(dev->win_base);
0326             dev->win_base = NULL;
0327         }
0328     }
0329     pcmcia_disable_device(link);
0330 }
0331 
0332 
0333 static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
0334                 tuple_t *tuple,
0335                 void *priv_data)
0336 {
0337     cisparse_t parse;
0338 
0339     if (!pcmcia_parse_tuple(tuple, &parse)) {
0340         cistpl_format_t *t = &parse.format;
0341         (void)t; /* Shut up, gcc */
0342         pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n",
0343             t->type, t->edc, t->offset, t->length);
0344     }
0345     return -ENOSPC;
0346 }
0347 
0348 static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
0349                 tuple_t *tuple,
0350                 void *priv_data)
0351 {
0352     cisparse_t parse;
0353     int i;
0354 
0355     if (!pcmcia_parse_tuple(tuple, &parse)) {
0356         cistpl_jedec_t *t = &parse.jedec;
0357         for (i = 0; i < t->nid; i++)
0358             pr_debug("JEDEC: 0x%02x 0x%02x\n",
0359                   t->id[i].mfr, t->id[i].info);
0360     }
0361     return -ENOSPC;
0362 }
0363 
0364 static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
0365                 tuple_t *tuple,
0366                 void *priv_data)
0367 {
0368     struct pcmciamtd_dev *dev = priv_data;
0369     cisparse_t parse;
0370     cistpl_device_t *t = &parse.device;
0371     int i;
0372 
0373     if (pcmcia_parse_tuple(tuple, &parse))
0374         return -EINVAL;
0375 
0376     pr_debug("Common memory:\n");
0377     dev->pcmcia_map.size = t->dev[0].size;
0378     /* from here on: DEBUG only */
0379     for (i = 0; i < t->ndev; i++) {
0380         pr_debug("Region %d, type = %u\n", i, t->dev[i].type);
0381         pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp);
0382         pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed);
0383         pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size);
0384     }
0385     return 0;
0386 }
0387 
0388 static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
0389                 tuple_t *tuple,
0390                 void *priv_data)
0391 {
0392     struct pcmciamtd_dev *dev = priv_data;
0393     cisparse_t parse;
0394     cistpl_device_geo_t *t = &parse.device_geo;
0395     int i;
0396 
0397     if (pcmcia_parse_tuple(tuple, &parse))
0398         return -EINVAL;
0399 
0400     dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
0401     /* from here on: DEBUG only */
0402     for (i = 0; i < t->ngeo; i++) {
0403         pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth);
0404         pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block);
0405         pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block);
0406         pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block);
0407         pr_debug("region: %d partition = %u\n", i, t->geo[i].partition);
0408         pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave);
0409     }
0410     return 0;
0411 }
0412 
0413 
0414 static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev, int *new_name)
0415 {
0416     int i;
0417 
0418     if (p_dev->prod_id[0]) {
0419         dev->mtd_name[0] = '\0';
0420         for (i = 0; i < 4; i++) {
0421             if (i)
0422                 strcat(dev->mtd_name, " ");
0423             if (p_dev->prod_id[i])
0424                 strcat(dev->mtd_name, p_dev->prod_id[i]);
0425         }
0426         pr_debug("Found name: %s\n", dev->mtd_name);
0427     }
0428 
0429     pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL);
0430     pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL);
0431     pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev);
0432     pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev);
0433 
0434     if(!dev->pcmcia_map.size)
0435         dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
0436 
0437     if(!dev->pcmcia_map.bankwidth)
0438         dev->pcmcia_map.bankwidth = 2;
0439 
0440     if(force_size) {
0441         dev->pcmcia_map.size = force_size << 20;
0442         pr_debug("size forced to %dM\n", force_size);
0443     }
0444 
0445     if(bankwidth) {
0446         dev->pcmcia_map.bankwidth = bankwidth;
0447         pr_debug("bankwidth forced to %d\n", bankwidth);
0448     }
0449 
0450     dev->pcmcia_map.name = dev->mtd_name;
0451     if(!dev->mtd_name[0]) {
0452         strcpy(dev->mtd_name, "PCMCIA Memory card");
0453         *new_name = 1;
0454     }
0455 
0456     pr_debug("Device: Size: %lu Width:%d Name: %s\n",
0457           dev->pcmcia_map.size,
0458           dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
0459 }
0460 
0461 
0462 static int pcmciamtd_config(struct pcmcia_device *link)
0463 {
0464     struct pcmciamtd_dev *dev = link->priv;
0465     struct mtd_info *mtd = NULL;
0466     int ret;
0467     int i, j = 0;
0468     static char *probes[] = { "jedec_probe", "cfi_probe" };
0469     int new_name = 0;
0470 
0471     pr_debug("link=0x%p\n", link);
0472 
0473     card_settings(dev, link, &new_name);
0474 
0475     dev->pcmcia_map.phys = NO_XIP;
0476     dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
0477     dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
0478     if (dev->pcmcia_map.bankwidth == 1) {
0479         dev->pcmcia_map.read = pcmcia_read8_remap;
0480         dev->pcmcia_map.write = pcmcia_write8_remap;
0481     } else {
0482         dev->pcmcia_map.read = pcmcia_read16_remap;
0483         dev->pcmcia_map.write = pcmcia_write16_remap;
0484     }
0485     if(setvpp == 1)
0486         dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
0487 
0488     /* Request a memory window for PCMCIA. Some architeures can map windows
0489      * up to the maximum that PCMCIA can support (64MiB) - this is ideal and
0490      * we aim for a window the size of the whole card - otherwise we try
0491      * smaller windows until we succeed
0492      */
0493 
0494     link->resource[2]->flags |=  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
0495     link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
0496                     WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
0497     link->resource[2]->start = 0;
0498     link->resource[2]->end = (force_size) ? force_size << 20 :
0499                     MAX_PCMCIA_ADDR;
0500     dev->win_size = 0;
0501 
0502     do {
0503         int ret;
0504         pr_debug("requesting window with size = %luKiB memspeed = %d\n",
0505             (unsigned long) resource_size(link->resource[2]) >> 10,
0506             mem_speed);
0507         ret = pcmcia_request_window(link, link->resource[2], mem_speed);
0508         pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
0509         if(ret) {
0510             j++;
0511             link->resource[2]->start = 0;
0512             link->resource[2]->end = (force_size) ?
0513                     force_size << 20 : MAX_PCMCIA_ADDR;
0514             link->resource[2]->end >>= j;
0515         } else {
0516             pr_debug("Got window of size %luKiB\n", (unsigned long)
0517                 resource_size(link->resource[2]) >> 10);
0518             dev->win_size = resource_size(link->resource[2]);
0519             break;
0520         }
0521     } while (link->resource[2]->end >= 0x1000);
0522 
0523     pr_debug("dev->win_size = %d\n", dev->win_size);
0524 
0525     if(!dev->win_size) {
0526         dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
0527         pcmciamtd_release(link);
0528         return -ENODEV;
0529     }
0530     pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);
0531 
0532     /* Get write protect status */
0533     dev->win_base = ioremap(link->resource[2]->start,
0534                 resource_size(link->resource[2]));
0535     if(!dev->win_base) {
0536         dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
0537             link->resource[2]);
0538         pcmciamtd_release(link);
0539         return -ENODEV;
0540     }
0541     pr_debug("mapped window dev = %p @ %pR, base = %p\n",
0542           dev, link->resource[2], dev->win_base);
0543 
0544     dev->offset = 0;
0545     dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
0546     dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
0547 
0548     dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
0549     if(setvpp == 2) {
0550         link->vpp = dev->vpp;
0551     } else {
0552         link->vpp = 0;
0553     }
0554 
0555     link->config_index = 0;
0556     pr_debug("Setting Configuration\n");
0557     ret = pcmcia_enable_device(link);
0558     if (ret != 0) {
0559         if (dev->win_base) {
0560             iounmap(dev->win_base);
0561             dev->win_base = NULL;
0562         }
0563         return -ENODEV;
0564     }
0565 
0566     if(mem_type == 1) {
0567         mtd = do_map_probe("map_ram", &dev->pcmcia_map);
0568     } else if(mem_type == 2) {
0569         mtd = do_map_probe("map_rom", &dev->pcmcia_map);
0570     } else {
0571         for(i = 0; i < ARRAY_SIZE(probes); i++) {
0572             pr_debug("Trying %s\n", probes[i]);
0573             mtd = do_map_probe(probes[i], &dev->pcmcia_map);
0574             if(mtd)
0575                 break;
0576 
0577             pr_debug("FAILED: %s\n", probes[i]);
0578         }
0579     }
0580 
0581     if(!mtd) {
0582         pr_debug("Can not find an MTD\n");
0583         pcmciamtd_release(link);
0584         return -ENODEV;
0585     }
0586 
0587     dev->mtd_info = mtd;
0588     mtd->owner = THIS_MODULE;
0589 
0590     if(new_name) {
0591         int size = 0;
0592         char unit = ' ';
0593         /* Since we are using a default name, make it better by adding
0594          * in the size
0595          */
0596         if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
0597             size = mtd->size >> 10;
0598             unit = 'K';
0599         } else {
0600             size = mtd->size >> 20;
0601             unit = 'M';
0602         }
0603         snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
0604     }
0605 
0606     /* If the memory found is fits completely into the mapped PCMCIA window,
0607        use the faster non-remapping read/write functions */
0608     if(mtd->size <= dev->win_size) {
0609         pr_debug("Using non remapping memory functions\n");
0610         dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
0611         if (dev->pcmcia_map.bankwidth == 1) {
0612             dev->pcmcia_map.read = pcmcia_read8;
0613             dev->pcmcia_map.write = pcmcia_write8;
0614         } else {
0615             dev->pcmcia_map.read = pcmcia_read16;
0616             dev->pcmcia_map.write = pcmcia_write16;
0617         }
0618         dev->pcmcia_map.copy_from = pcmcia_copy_from;
0619         dev->pcmcia_map.copy_to = pcmcia_copy_to;
0620     }
0621 
0622     if (mtd_device_register(mtd, NULL, 0)) {
0623         map_destroy(mtd);
0624         dev->mtd_info = NULL;
0625         dev_err(&dev->p_dev->dev,
0626             "Could not register the MTD device\n");
0627         pcmciamtd_release(link);
0628         return -ENODEV;
0629     }
0630     dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
0631     return 0;
0632 }
0633 
0634 
0635 static int pcmciamtd_suspend(struct pcmcia_device *dev)
0636 {
0637     pr_debug("EVENT_PM_RESUME\n");
0638 
0639     /* get_lock(link); */
0640 
0641     return 0;
0642 }
0643 
0644 static int pcmciamtd_resume(struct pcmcia_device *dev)
0645 {
0646     pr_debug("EVENT_PM_SUSPEND\n");
0647 
0648     /* free_lock(link); */
0649 
0650     return 0;
0651 }
0652 
0653 
0654 static void pcmciamtd_detach(struct pcmcia_device *link)
0655 {
0656     struct pcmciamtd_dev *dev = link->priv;
0657 
0658     pr_debug("link=0x%p\n", link);
0659 
0660     if(dev->mtd_info) {
0661         mtd_device_unregister(dev->mtd_info);
0662         dev_info(&dev->p_dev->dev, "mtd%d: Removing\n",
0663              dev->mtd_info->index);
0664         map_destroy(dev->mtd_info);
0665     }
0666 
0667     pcmciamtd_release(link);
0668 }
0669 
0670 
0671 static int pcmciamtd_probe(struct pcmcia_device *link)
0672 {
0673     struct pcmciamtd_dev *dev;
0674 
0675     /* Create new memory card device */
0676     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0677     if (!dev) return -ENOMEM;
0678     pr_debug("dev=0x%p\n", dev);
0679 
0680     dev->p_dev = link;
0681     link->priv = dev;
0682 
0683     return pcmciamtd_config(link);
0684 }
0685 
0686 static const struct pcmcia_device_id pcmciamtd_ids[] = {
0687     PCMCIA_DEVICE_FUNC_ID(1),
0688     PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21),
0689     PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21),
0690     PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a),
0691     PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e),
0692     PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf),
0693     PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb),
0694     PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c),
0695     PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda),
0696     PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0),
0697     PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8),
0698     PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c),
0699     PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0),
0700     PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965),
0701     PCMCIA_DEVICE_PROD_ID12("PRETEC", "  2MB SRAM CARD", 0xebf91155, 0x805360ca),
0702     PCMCIA_DEVICE_PROD_ID12("PRETEC", "  4MB SRAM CARD", 0xebf91155, 0x20b6bf17),
0703     PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b),
0704     PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad),
0705     PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05),
0706     PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca),
0707     PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944),
0708     /* the following was commented out in pcmcia-cs-3.2.7 */
0709     /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */
0710 #ifdef CONFIG_MTD_PCMCIA_ANONYMOUS
0711     { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, },
0712 #endif
0713     PCMCIA_DEVICE_NULL
0714 };
0715 MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
0716 
0717 static struct pcmcia_driver pcmciamtd_driver = {
0718     .name       = "pcmciamtd",
0719     .probe      = pcmciamtd_probe,
0720     .remove     = pcmciamtd_detach,
0721     .owner      = THIS_MODULE,
0722     .id_table   = pcmciamtd_ids,
0723     .suspend    = pcmciamtd_suspend,
0724     .resume     = pcmciamtd_resume,
0725 };
0726 
0727 
0728 static int __init init_pcmciamtd(void)
0729 {
0730     if(bankwidth && bankwidth != 1 && bankwidth != 2) {
0731         info("bad bankwidth (%d), using default", bankwidth);
0732         bankwidth = 2;
0733     }
0734     if(force_size && (force_size < 1 || force_size > 64)) {
0735         info("bad force_size (%d), using default", force_size);
0736         force_size = 0;
0737     }
0738     if(mem_type && mem_type != 1 && mem_type != 2) {
0739         info("bad mem_type (%d), using default", mem_type);
0740         mem_type = 0;
0741     }
0742     return pcmcia_register_driver(&pcmciamtd_driver);
0743 }
0744 
0745 
0746 static void __exit exit_pcmciamtd(void)
0747 {
0748     pr_debug(DRIVER_DESC " unloading");
0749     pcmcia_unregister_driver(&pcmciamtd_driver);
0750 }
0751 
0752 module_init(init_pcmciamtd);
0753 module_exit(exit_pcmciamtd);