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