This source file includes following definitions.
- mtd_pci_read8
- mtd_pci_read32
- mtd_pci_copyfrom
- mtd_pci_write8
- mtd_pci_write32
- mtd_pci_copyto
- intel_iq80310_init
- intel_iq80310_exit
- intel_iq80310_translate
- intel_dc21285_init
- intel_dc21285_exit
- intel_dc21285_translate
- mtd_pci_probe
- mtd_pci_remove
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/module.h>
  12 #include <linux/kernel.h>
  13 #include <linux/pci.h>
  14 #include <linux/slab.h>
  15 
  16 #include <linux/mtd/mtd.h>
  17 #include <linux/mtd/map.h>
  18 #include <linux/mtd/partitions.h>
  19 
  20 struct map_pci_info;
  21 
  22 struct mtd_pci_info {
  23         int  (*init)(struct pci_dev *dev, struct map_pci_info *map);
  24         void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
  25         unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
  26         const char *map_name;
  27 };
  28 
  29 struct map_pci_info {
  30         struct map_info map;
  31         void __iomem *base;
  32         void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
  33         unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
  34         struct pci_dev *dev;
  35 };
  36 
  37 static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
  38 {
  39         struct map_pci_info *map = (struct map_pci_info *)_map;
  40         map_word val;
  41         val.x[0]= readb(map->base + map->translate(map, ofs));
  42         return val;
  43 }
  44 
  45 static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
  46 {
  47         struct map_pci_info *map = (struct map_pci_info *)_map;
  48         map_word val;
  49         val.x[0] = readl(map->base + map->translate(map, ofs));
  50         return val;
  51 }
  52 
  53 static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
  54 {
  55         struct map_pci_info *map = (struct map_pci_info *)_map;
  56         memcpy_fromio(to, map->base + map->translate(map, from), len);
  57 }
  58 
  59 static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
  60 {
  61         struct map_pci_info *map = (struct map_pci_info *)_map;
  62         writeb(val.x[0], map->base + map->translate(map, ofs));
  63 }
  64 
  65 static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
  66 {
  67         struct map_pci_info *map = (struct map_pci_info *)_map;
  68         writel(val.x[0], map->base + map->translate(map, ofs));
  69 }
  70 
  71 static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
  72 {
  73         struct map_pci_info *map = (struct map_pci_info *)_map;
  74         memcpy_toio(map->base + map->translate(map, to), from, len);
  75 }
  76 
  77 static const struct map_info mtd_pci_map = {
  78         .phys =         NO_XIP,
  79         .copy_from =    mtd_pci_copyfrom,
  80         .copy_to =      mtd_pci_copyto,
  81 };
  82 
  83 
  84 
  85 
  86 
  87 static int
  88 intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
  89 {
  90         u32 win_base;
  91 
  92         map->map.bankwidth = 1;
  93         map->map.read = mtd_pci_read8,
  94         map->map.write = mtd_pci_write8,
  95 
  96         map->map.size     = 0x00800000;
  97         map->base         = ioremap_nocache(pci_resource_start(dev, 0),
  98                                             pci_resource_len(dev, 0));
  99 
 100         if (!map->base)
 101                 return -ENOMEM;
 102 
 103         
 104 
 105 
 106 
 107         pci_read_config_dword(dev, 0x44, &win_base);
 108         pci_write_config_dword(dev, 0x44, 0);
 109 
 110         map->map.map_priv_2 = win_base;
 111 
 112         return 0;
 113 }
 114 
 115 static void
 116 intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
 117 {
 118         if (map->base)
 119                 iounmap(map->base);
 120         pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
 121 }
 122 
 123 static unsigned long
 124 intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
 125 {
 126         unsigned long page_addr = ofs & 0x00400000;
 127 
 128         
 129 
 130 
 131 
 132         if (page_addr) {
 133                 writel(0x00000008, map->base + 0x1558);
 134                 writel(0x00000000, map->base + 0x1550);
 135         } else {
 136                 writel(0x00000007, map->base + 0x1558);
 137                 writel(0x00800000, map->base + 0x1550);
 138                 ofs += 0x00800000;
 139         }
 140 
 141         return ofs;
 142 }
 143 
 144 static struct mtd_pci_info intel_iq80310_info = {
 145         .init =         intel_iq80310_init,
 146         .exit =         intel_iq80310_exit,
 147         .translate =    intel_iq80310_translate,
 148         .map_name =     "cfi_probe",
 149 };
 150 
 151 
 152 
 153 
 154 
 155 static int
 156 intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
 157 {
 158         unsigned long base, len;
 159 
 160         base = pci_resource_start(dev, PCI_ROM_RESOURCE);
 161         len  = pci_resource_len(dev, PCI_ROM_RESOURCE);
 162 
 163         if (!len || !base) {
 164                 
 165 
 166 
 167                 base = pci_resource_start(dev, 2);
 168                 len  = pci_resource_len(dev, 2);
 169 
 170                 
 171 
 172 
 173 
 174         } else {
 175                 
 176 
 177 
 178 
 179 
 180                 pci_enable_rom(dev);
 181                 printk("%s: enabling expansion ROM\n", pci_name(dev));
 182         }
 183 
 184         if (!len || !base)
 185                 return -ENXIO;
 186 
 187         map->map.bankwidth = 4;
 188         map->map.read = mtd_pci_read32,
 189         map->map.write = mtd_pci_write32,
 190         map->map.size     = len;
 191         map->base         = ioremap_nocache(base, len);
 192 
 193         if (!map->base)
 194                 return -ENOMEM;
 195 
 196         return 0;
 197 }
 198 
 199 static void
 200 intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
 201 {
 202         if (map->base)
 203                 iounmap(map->base);
 204 
 205         
 206 
 207 
 208         pci_disable_rom(dev);
 209 }
 210 
 211 static unsigned long
 212 intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
 213 {
 214         return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
 215 }
 216 
 217 static struct mtd_pci_info intel_dc21285_info = {
 218         .init =         intel_dc21285_init,
 219         .exit =         intel_dc21285_exit,
 220         .translate =    intel_dc21285_translate,
 221         .map_name =     "jedec_probe",
 222 };
 223 
 224 
 225 
 226 
 227 
 228 static const struct pci_device_id mtd_pci_ids[] = {
 229         {
 230                 .vendor =       PCI_VENDOR_ID_INTEL,
 231                 .device =       0x530d,
 232                 .subvendor =    PCI_ANY_ID,
 233                 .subdevice =    PCI_ANY_ID,
 234                 .class =        PCI_CLASS_MEMORY_OTHER << 8,
 235                 .class_mask =   0xffff00,
 236                 .driver_data =  (unsigned long)&intel_iq80310_info,
 237         },
 238         {
 239                 .vendor =       PCI_VENDOR_ID_DEC,
 240                 .device =       PCI_DEVICE_ID_DEC_21285,
 241                 .subvendor =    0,      
 242                 .subdevice =    0,      
 243                 .driver_data =  (unsigned long)&intel_dc21285_info,
 244         },
 245         { 0, }
 246 };
 247 
 248 
 249 
 250 
 251 
 252 static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 253 {
 254         struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
 255         struct map_pci_info *map = NULL;
 256         struct mtd_info *mtd = NULL;
 257         int err;
 258 
 259         err = pci_enable_device(dev);
 260         if (err)
 261                 goto out;
 262 
 263         err = pci_request_regions(dev, "pci mtd");
 264         if (err)
 265                 goto out;
 266 
 267         map = kmalloc(sizeof(*map), GFP_KERNEL);
 268         err = -ENOMEM;
 269         if (!map)
 270                 goto release;
 271 
 272         map->map       = mtd_pci_map;
 273         map->map.name  = pci_name(dev);
 274         map->dev       = dev;
 275         map->exit      = info->exit;
 276         map->translate = info->translate;
 277 
 278         err = info->init(dev, map);
 279         if (err)
 280                 goto release;
 281 
 282         mtd = do_map_probe(info->map_name, &map->map);
 283         err = -ENODEV;
 284         if (!mtd)
 285                 goto release;
 286 
 287         mtd->owner = THIS_MODULE;
 288         mtd_device_register(mtd, NULL, 0);
 289 
 290         pci_set_drvdata(dev, mtd);
 291 
 292         return 0;
 293 
 294 release:
 295         if (map) {
 296                 map->exit(dev, map);
 297                 kfree(map);
 298         }
 299 
 300         pci_release_regions(dev);
 301 out:
 302         return err;
 303 }
 304 
 305 static void mtd_pci_remove(struct pci_dev *dev)
 306 {
 307         struct mtd_info *mtd = pci_get_drvdata(dev);
 308         struct map_pci_info *map = mtd->priv;
 309 
 310         mtd_device_unregister(mtd);
 311         map_destroy(mtd);
 312         map->exit(dev, map);
 313         kfree(map);
 314 
 315         pci_release_regions(dev);
 316 }
 317 
 318 static struct pci_driver mtd_pci_driver = {
 319         .name =         "MTD PCI",
 320         .probe =        mtd_pci_probe,
 321         .remove =       mtd_pci_remove,
 322         .id_table =     mtd_pci_ids,
 323 };
 324 
 325 module_pci_driver(mtd_pci_driver);
 326 
 327 MODULE_LICENSE("GPL");
 328 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 329 MODULE_DESCRIPTION("Generic PCI map driver");
 330 MODULE_DEVICE_TABLE(pci, mtd_pci_ids);