root/drivers/mtd/maps/pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mtd_pci_read8
  2. mtd_pci_read32
  3. mtd_pci_copyfrom
  4. mtd_pci_write8
  5. mtd_pci_write32
  6. mtd_pci_copyto
  7. intel_iq80310_init
  8. intel_iq80310_exit
  9. intel_iq80310_translate
  10. intel_dc21285_init
  11. intel_dc21285_exit
  12. intel_dc21285_translate
  13. mtd_pci_probe
  14. mtd_pci_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/drivers/mtd/maps/pci.c
   4  *
   5  *  Copyright (C) 2001 Russell King, All rights reserved.
   6  *
   7  * Generic PCI memory map driver.  We support the following boards:
   8  *  - Intel IQ80310 ATU.
   9  *  - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
  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  * Intel IOP80310 Flash driver
  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          * We want to base the memory window at Xscale
 105          * bus address 0, not 0x1000.
 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          * This mundges the flash location so we avoid
 130          * the first 80 bytes (they appear to read nonsense).
 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  * Intel DC21285 driver
 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                  * No ROM resource
 166                  */
 167                 base = pci_resource_start(dev, 2);
 168                 len  = pci_resource_len(dev, 2);
 169 
 170                 /*
 171                  * We need to re-allocate PCI BAR2 address range to the
 172                  * PCI ROM BAR, and disable PCI BAR2.
 173                  */
 174         } else {
 175                 /*
 176                  * Hmm, if an address was allocated to the ROM resource, but
 177                  * not enabled, should we be allocating a new resource for it
 178                  * or simply enabling it?
 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          * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
 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  * PCI device ID table
 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,      /* DC21285 defaults to 0 on reset */
 242                 .subdevice =    0,      /* DC21285 defaults to 0 on reset */
 243                 .driver_data =  (unsigned long)&intel_dc21285_info,
 244         },
 245         { 0, }
 246 };
 247 
 248 /*
 249  * Generic code follows.
 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);

/* [<][>][^][v][top][bottom][index][help] */