1 /* 2 * linux/drivers/mtd/maps/pci.c 3 * 4 * Copyright (C) 2001 Russell King, All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * $Id: pci.c,v 1.14 2005/11/17 08:20:27 dwmw2 Exp $ 11 * 12 * Generic PCI memory map driver. We support the following boards: 13 * - Intel IQ80310 ATU. 14 * - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001 15 */ 16 #include <linux/module.h> 17 #include <linux/kernel.h> 18 #include <linux/pci.h> 19 #include <linux/init.h> 20 #include <linux/slab.h> 21 22 #include <linux/mtd/mtd.h> 23 #include <linux/mtd/map.h> 24 #include <linux/mtd/partitions.h> 25 26 struct map_pci_info; 27 28 struct mtd_pci_info { 29 int (*init)(struct pci_dev *dev, struct map_pci_info *map); 30 void (*exit)(struct pci_dev *dev, struct map_pci_info *map); 31 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs); 32 const char *map_name; 33 }; 34 35 struct map_pci_info { 36 struct map_info map; 37 void __iomem *base; 38 void (*exit)(struct pci_dev *dev, struct map_pci_info *map); 39 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs); 40 struct pci_dev *dev; 41 }; 42 43 static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs) 44 { 45 struct map_pci_info *map = (struct map_pci_info *)_map; 46 map_word val; 47 val.x[0]= readb(map->base + map->translate(map, ofs)); 48 // printk("read8 : %08lx => %02x\n", ofs, val.x[0]); 49 return val; 50 } 51 52 #if 0 53 static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs) 54 { 55 struct map_pci_info *map = (struct map_pci_info *)_map; 56 map_word val; 57 val.x[0] = readw(map->base + map->translate(map, ofs)); 58 // printk("read16: %08lx => %04x\n", ofs, val.x[0]); 59 return val; 60 } 61 #endif 62 static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs) 63 { 64 struct map_pci_info *map = (struct map_pci_info *)_map; 65 map_word val; 66 val.x[0] = readl(map->base + map->translate(map, ofs)); 67 // printk("read32: %08lx => %08x\n", ofs, val.x[0]); 68 return val; 69 } 70 71 static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len) 72 { 73 struct map_pci_info *map = (struct map_pci_info *)_map; 74 memcpy_fromio(to, map->base + map->translate(map, from), len); 75 } 76 77 static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs) 78 { 79 struct map_pci_info *map = (struct map_pci_info *)_map; 80 // printk("write8 : %08lx <= %02x\n", ofs, val.x[0]); 81 writeb(val.x[0], map->base + map->translate(map, ofs)); 82 } 83 84 #if 0 85 static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs) 86 { 87 struct map_pci_info *map = (struct map_pci_info *)_map; 88 // printk("write16: %08lx <= %04x\n", ofs, val.x[0]); 89 writew(val.x[0], map->base + map->translate(map, ofs)); 90 } 91 #endif 92 static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs) 93 { 94 struct map_pci_info *map = (struct map_pci_info *)_map; 95 // printk("write32: %08lx <= %08x\n", ofs, val.x[0]); 96 writel(val.x[0], map->base + map->translate(map, ofs)); 97 } 98 99 static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len) 100 { 101 struct map_pci_info *map = (struct map_pci_info *)_map; 102 memcpy_toio(map->base + map->translate(map, to), from, len); 103 } 104 105 static const struct map_info mtd_pci_map = { 106 .phys = NO_XIP, 107 .copy_from = mtd_pci_copyfrom, 108 .copy_to = mtd_pci_copyto, 109 }; 110 111 /* 112 * Intel IOP80310 Flash driver 113 */ 114 115 static int 116 intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map) 117 { 118 u32 win_base; 119 120 map->map.bankwidth = 1; 121 map->map.read = mtd_pci_read8, 122 map->map.write = mtd_pci_write8, 123 124 map->map.size = 0x00800000; 125 map->base = ioremap_nocache(pci_resource_start(dev, 0), 126 pci_resource_len(dev, 0)); 127 128 if (!map->base) 129 return -ENOMEM; 130 131 /* 132 * We want to base the memory window at Xscale 133 * bus address 0, not 0x1000. 134 */ 135 pci_read_config_dword(dev, 0x44, &win_base); 136 pci_write_config_dword(dev, 0x44, 0); 137 138 map->map.map_priv_2 = win_base; 139 140 return 0; 141 } 142 143 static void 144 intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map) 145 { 146 if (map->base) 147 iounmap(map->base); 148 pci_write_config_dword(dev, 0x44, map->map.map_priv_2); 149 } 150 151 static unsigned long 152 intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs) 153 { 154 unsigned long page_addr = ofs & 0x00400000; 155 156 /* 157 * This mundges the flash location so we avoid 158 * the first 80 bytes (they appear to read nonsense). 159 */ 160 if (page_addr) { 161 writel(0x00000008, map->base + 0x1558); 162 writel(0x00000000, map->base + 0x1550); 163 } else { 164 writel(0x00000007, map->base + 0x1558); 165 writel(0x00800000, map->base + 0x1550); 166 ofs += 0x00800000; 167 } 168 169 return ofs; 170 } 171 172 static struct mtd_pci_info intel_iq80310_info = { 173 .init = intel_iq80310_init, 174 .exit = intel_iq80310_exit, 175 .translate = intel_iq80310_translate, 176 .map_name = "cfi_probe", 177 }; 178 179 /* 180 * Intel DC21285 driver 181 */ 182 183 static int 184 intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map) 185 { 186 unsigned long base, len; 187 188 base = pci_resource_start(dev, PCI_ROM_RESOURCE); 189 len = pci_resource_len(dev, PCI_ROM_RESOURCE); 190 191 if (!len || !base) { 192 /* 193 * No ROM resource 194 */ 195 base = pci_resource_start(dev, 2); 196 len = pci_resource_len(dev, 2); 197 198 /* 199 * We need to re-allocate PCI BAR2 address range to the 200 * PCI ROM BAR, and disable PCI BAR2. 201 */ 202 } else { 203 /* 204 * Hmm, if an address was allocated to the ROM resource, but 205 * not enabled, should we be allocating a new resource for it 206 * or simply enabling it? 207 */ 208 if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) & 209 IORESOURCE_ROM_ENABLE)) { 210 u32 val; 211 pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE; 212 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val); 213 val |= PCI_ROM_ADDRESS_ENABLE; 214 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val); 215 printk("%s: enabling expansion ROM\n", pci_name(dev)); 216 } 217 } 218 219 if (!len || !base) 220 return -ENXIO; 221 222 map->map.bankwidth = 4; 223 map->map.read = mtd_pci_read32, 224 map->map.write = mtd_pci_write32, 225 map->map.size = len; 226 map->base = ioremap_nocache(base, len); 227 228 if (!map->base) 229 return -ENOMEM; 230 231 return 0; 232 } 233 234 static void 235 intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map) 236 { 237 u32 val; 238 239 if (map->base) 240 iounmap(map->base); 241 242 /* 243 * We need to undo the PCI BAR2/PCI ROM BAR address alteration. 244 */ 245 pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE; 246 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val); 247 val &= ~PCI_ROM_ADDRESS_ENABLE; 248 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val); 249 } 250 251 static unsigned long 252 intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs) 253 { 254 return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5)); 255 } 256 257 static struct mtd_pci_info intel_dc21285_info = { 258 .init = intel_dc21285_init, 259 .exit = intel_dc21285_exit, 260 .translate = intel_dc21285_translate, 261 .map_name = "jedec_probe", 262 }; 263 264 /* 265 * PCI device ID table 266 */ 267 268 static struct pci_device_id mtd_pci_ids[] = { 269 { 270 .vendor = PCI_VENDOR_ID_INTEL, 271 .device = 0x530d, 272 .subvendor = PCI_ANY_ID, 273 .subdevice = PCI_ANY_ID, 274 .class = PCI_CLASS_MEMORY_OTHER << 8, 275 .class_mask = 0xffff00, 276 .driver_data = (unsigned long)&intel_iq80310_info, 277 }, 278 { 279 .vendor = PCI_VENDOR_ID_DEC, 280 .device = PCI_DEVICE_ID_DEC_21285, 281 .subvendor = 0, /* DC21285 defaults to 0 on reset */ 282 .subdevice = 0, /* DC21285 defaults to 0 on reset */ 283 .driver_data = (unsigned long)&intel_dc21285_info, 284 }, 285 { 0, } 286 }; 287 288 /* 289 * Generic code follows. 290 */ 291 292 static int __devinit 293 mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 294 { 295 struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data; 296 struct map_pci_info *map = NULL; 297 struct mtd_info *mtd = NULL; 298 int err; 299 300 err = pci_enable_device(dev); 301 if (err) 302 goto out; 303 304 err = pci_request_regions(dev, "pci mtd"); 305 if (err) 306 goto out; 307 308 map = kmalloc(sizeof(*map), GFP_KERNEL); 309 err = -ENOMEM; 310 if (!map) 311 goto release; 312 313 map->map = mtd_pci_map; 314 map->map.name = pci_name(dev); 315 map->dev = dev; 316 map->exit = info->exit; 317 map->translate = info->translate; 318 319 err = info->init(dev, map); 320 if (err) 321 goto release; 322 323 /* tsk - do_map_probe should take const char * */ 324 mtd = do_map_probe((char *)info->map_name, &map->map); 325 err = -ENODEV; 326 if (!mtd) 327 goto release; 328 329 mtd->owner = THIS_MODULE; 330 add_mtd_device(mtd); 331 332 pci_set_drvdata(dev, mtd); 333 334 return 0; 335 336 release: 337 if (map) { 338 map->exit(dev, map); 339 kfree(map); 340 } 341 342 pci_release_regions(dev); 343 out: 344 return err; 345 } 346 347 static void __devexit 348 mtd_pci_remove(struct pci_dev *dev) 349 { 350 struct mtd_info *mtd = pci_get_drvdata(dev); 351 struct map_pci_info *map = mtd->priv; 352 353 del_mtd_device(mtd); 354 map_destroy(mtd); 355 map->exit(dev, map); 356 kfree(map); 357 358 pci_set_drvdata(dev, NULL); 359 pci_release_regions(dev); 360 } 361 362 static struct pci_driver mtd_pci_driver = { 363 .name = "MTD PCI", 364 .probe = mtd_pci_probe, 365 .remove = __devexit_p(mtd_pci_remove), 366 .id_table = mtd_pci_ids, 367 }; 368 369 static int __init mtd_pci_maps_init(void) 370 { 371 return pci_register_driver(&mtd_pci_driver); 372 } 373 374 static void __exit mtd_pci_maps_exit(void) 375 { 376 pci_unregister_driver(&mtd_pci_driver); 377 } 378 379 module_init(mtd_pci_maps_init); 380 module_exit(mtd_pci_maps_exit); 381 382 MODULE_LICENSE("GPL"); 383 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 384 MODULE_DESCRIPTION("Generic PCI map driver"); 385 MODULE_DEVICE_TABLE(pci, mtd_pci_ids); 386 387