Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/drivers/mtd/maps/pci.c
0004  *
0005  *  Copyright (C) 2001 Russell King, All rights reserved.
0006  *
0007  * Generic PCI memory map driver.  We support the following boards:
0008  *  - Intel IQ80310 ATU.
0009  *  - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
0010  */
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/pci.h>
0014 #include <linux/slab.h>
0015 
0016 #include <linux/mtd/mtd.h>
0017 #include <linux/mtd/map.h>
0018 #include <linux/mtd/partitions.h>
0019 
0020 struct map_pci_info;
0021 
0022 struct mtd_pci_info {
0023     int  (*init)(struct pci_dev *dev, struct map_pci_info *map);
0024     void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
0025     unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
0026     const char *map_name;
0027 };
0028 
0029 struct map_pci_info {
0030     struct map_info map;
0031     void __iomem *base;
0032     void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
0033     unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
0034     struct pci_dev *dev;
0035 };
0036 
0037 static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
0038 {
0039     struct map_pci_info *map = (struct map_pci_info *)_map;
0040     map_word val;
0041     val.x[0]= readb(map->base + map->translate(map, ofs));
0042     return val;
0043 }
0044 
0045 static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
0046 {
0047     struct map_pci_info *map = (struct map_pci_info *)_map;
0048     map_word val;
0049     val.x[0] = readl(map->base + map->translate(map, ofs));
0050     return val;
0051 }
0052 
0053 static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
0054 {
0055     struct map_pci_info *map = (struct map_pci_info *)_map;
0056     memcpy_fromio(to, map->base + map->translate(map, from), len);
0057 }
0058 
0059 static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
0060 {
0061     struct map_pci_info *map = (struct map_pci_info *)_map;
0062     writeb(val.x[0], map->base + map->translate(map, ofs));
0063 }
0064 
0065 static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
0066 {
0067     struct map_pci_info *map = (struct map_pci_info *)_map;
0068     writel(val.x[0], map->base + map->translate(map, ofs));
0069 }
0070 
0071 static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
0072 {
0073     struct map_pci_info *map = (struct map_pci_info *)_map;
0074     memcpy_toio(map->base + map->translate(map, to), from, len);
0075 }
0076 
0077 static const struct map_info mtd_pci_map = {
0078     .phys =     NO_XIP,
0079     .copy_from =    mtd_pci_copyfrom,
0080     .copy_to =  mtd_pci_copyto,
0081 };
0082 
0083 /*
0084  * Intel IOP80310 Flash driver
0085  */
0086 
0087 static int
0088 intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
0089 {
0090     u32 win_base;
0091 
0092     map->map.bankwidth = 1;
0093     map->map.read = mtd_pci_read8;
0094     map->map.write = mtd_pci_write8;
0095 
0096     map->map.size     = 0x00800000;
0097     map->base         = ioremap(pci_resource_start(dev, 0),
0098                         pci_resource_len(dev, 0));
0099 
0100     if (!map->base)
0101         return -ENOMEM;
0102 
0103     /*
0104      * We want to base the memory window at Xscale
0105      * bus address 0, not 0x1000.
0106      */
0107     pci_read_config_dword(dev, 0x44, &win_base);
0108     pci_write_config_dword(dev, 0x44, 0);
0109 
0110     map->map.map_priv_2 = win_base;
0111 
0112     return 0;
0113 }
0114 
0115 static void
0116 intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
0117 {
0118     if (map->base)
0119         iounmap(map->base);
0120     pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
0121 }
0122 
0123 static unsigned long
0124 intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
0125 {
0126     unsigned long page_addr = ofs & 0x00400000;
0127 
0128     /*
0129      * This mundges the flash location so we avoid
0130      * the first 80 bytes (they appear to read nonsense).
0131      */
0132     if (page_addr) {
0133         writel(0x00000008, map->base + 0x1558);
0134         writel(0x00000000, map->base + 0x1550);
0135     } else {
0136         writel(0x00000007, map->base + 0x1558);
0137         writel(0x00800000, map->base + 0x1550);
0138         ofs += 0x00800000;
0139     }
0140 
0141     return ofs;
0142 }
0143 
0144 static struct mtd_pci_info intel_iq80310_info = {
0145     .init =     intel_iq80310_init,
0146     .exit =     intel_iq80310_exit,
0147     .translate =    intel_iq80310_translate,
0148     .map_name = "cfi_probe",
0149 };
0150 
0151 /*
0152  * Intel DC21285 driver
0153  */
0154 
0155 static int
0156 intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
0157 {
0158     unsigned long base, len;
0159 
0160     base = pci_resource_start(dev, PCI_ROM_RESOURCE);
0161     len  = pci_resource_len(dev, PCI_ROM_RESOURCE);
0162 
0163     if (!len || !base) {
0164         /*
0165          * No ROM resource
0166          */
0167         base = pci_resource_start(dev, 2);
0168         len  = pci_resource_len(dev, 2);
0169 
0170         /*
0171          * We need to re-allocate PCI BAR2 address range to the
0172          * PCI ROM BAR, and disable PCI BAR2.
0173          */
0174     } else {
0175         /*
0176          * Hmm, if an address was allocated to the ROM resource, but
0177          * not enabled, should we be allocating a new resource for it
0178          * or simply enabling it?
0179          */
0180         pci_enable_rom(dev);
0181         printk("%s: enabling expansion ROM\n", pci_name(dev));
0182     }
0183 
0184     if (!len || !base)
0185         return -ENXIO;
0186 
0187     map->map.bankwidth = 4;
0188     map->map.read = mtd_pci_read32;
0189     map->map.write = mtd_pci_write32;
0190     map->map.size     = len;
0191     map->base         = ioremap(base, len);
0192 
0193     if (!map->base)
0194         return -ENOMEM;
0195 
0196     return 0;
0197 }
0198 
0199 static void
0200 intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
0201 {
0202     if (map->base)
0203         iounmap(map->base);
0204 
0205     /*
0206      * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
0207      */
0208     pci_disable_rom(dev);
0209 }
0210 
0211 static unsigned long
0212 intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
0213 {
0214     return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
0215 }
0216 
0217 static struct mtd_pci_info intel_dc21285_info = {
0218     .init =     intel_dc21285_init,
0219     .exit =     intel_dc21285_exit,
0220     .translate =    intel_dc21285_translate,
0221     .map_name = "jedec_probe",
0222 };
0223 
0224 /*
0225  * PCI device ID table
0226  */
0227 
0228 static const struct pci_device_id mtd_pci_ids[] = {
0229     {
0230         .vendor =   PCI_VENDOR_ID_INTEL,
0231         .device =   0x530d,
0232         .subvendor =    PCI_ANY_ID,
0233         .subdevice =    PCI_ANY_ID,
0234         .class =    PCI_CLASS_MEMORY_OTHER << 8,
0235         .class_mask =   0xffff00,
0236         .driver_data =  (unsigned long)&intel_iq80310_info,
0237     },
0238     {
0239         .vendor =   PCI_VENDOR_ID_DEC,
0240         .device =   PCI_DEVICE_ID_DEC_21285,
0241         .subvendor =    0,  /* DC21285 defaults to 0 on reset */
0242         .subdevice =    0,  /* DC21285 defaults to 0 on reset */
0243         .driver_data =  (unsigned long)&intel_dc21285_info,
0244     },
0245     { 0, }
0246 };
0247 
0248 /*
0249  * Generic code follows.
0250  */
0251 
0252 static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
0253 {
0254     struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
0255     struct map_pci_info *map = NULL;
0256     struct mtd_info *mtd = NULL;
0257     int err;
0258 
0259     err = pci_enable_device(dev);
0260     if (err)
0261         goto out;
0262 
0263     err = pci_request_regions(dev, "pci mtd");
0264     if (err)
0265         goto out;
0266 
0267     map = kmalloc(sizeof(*map), GFP_KERNEL);
0268     err = -ENOMEM;
0269     if (!map)
0270         goto release;
0271 
0272     map->map       = mtd_pci_map;
0273     map->map.name  = pci_name(dev);
0274     map->dev       = dev;
0275     map->exit      = info->exit;
0276     map->translate = info->translate;
0277 
0278     err = info->init(dev, map);
0279     if (err)
0280         goto release;
0281 
0282     mtd = do_map_probe(info->map_name, &map->map);
0283     err = -ENODEV;
0284     if (!mtd)
0285         goto release;
0286 
0287     mtd->owner = THIS_MODULE;
0288     mtd_device_register(mtd, NULL, 0);
0289 
0290     pci_set_drvdata(dev, mtd);
0291 
0292     return 0;
0293 
0294 release:
0295     if (map) {
0296         map->exit(dev, map);
0297         kfree(map);
0298     }
0299 
0300     pci_release_regions(dev);
0301 out:
0302     return err;
0303 }
0304 
0305 static void mtd_pci_remove(struct pci_dev *dev)
0306 {
0307     struct mtd_info *mtd = pci_get_drvdata(dev);
0308     struct map_pci_info *map = mtd->priv;
0309 
0310     mtd_device_unregister(mtd);
0311     map_destroy(mtd);
0312     map->exit(dev, map);
0313     kfree(map);
0314 
0315     pci_release_regions(dev);
0316 }
0317 
0318 static struct pci_driver mtd_pci_driver = {
0319     .name =     "MTD PCI",
0320     .probe =    mtd_pci_probe,
0321     .remove =   mtd_pci_remove,
0322     .id_table = mtd_pci_ids,
0323 };
0324 
0325 module_pci_driver(mtd_pci_driver);
0326 
0327 MODULE_LICENSE("GPL");
0328 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
0329 MODULE_DESCRIPTION("Generic PCI map driver");
0330 MODULE_DEVICE_TABLE(pci, mtd_pci_ids);