pcmciamtd.c revision 7c8d206f219fe52966d970f791246a542718e5ba
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pcmciamtd.c - MTD driver for PCMCIA flash memory cards 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Simon Evans <spse@secret.org.uk> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Simon Evans 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licence: GPL 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ds.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "PCMCIA Flash memory card driver" 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Size of the PCMCIA address space: 26 bits = 64 MB */ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PCMCIA_ADDR 0x4000000 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pcmciamtd_dev { 33fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski struct pcmcia_device *p_dev; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base; /* ioremapped address of PCMCIA window */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int win_size; /* size of window */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int offset; /* offset into card the window currently points at */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct map_info pcmcia_map; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_info *mtd_info; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vpp; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char mtd_name[sizeof(struct cistpl_vers_1_t)]; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Module parameters */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bankwidth = 2; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Speed of memory accesses, in ns */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mem_speed; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force the size of an SRAM card */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int force_size; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force Vpp */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int vpp; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set Vpp */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setvpp; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force card to be treated as FLASH, ROM or RAM */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mem_type; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 678d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(bankwidth, int, 0); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)"); 698d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(mem_speed, int, 0); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); 718d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(force_size, int, 0); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); 738d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(setvpp, int, 0); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); 758d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(vpp, int, 0); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)"); 778d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(mem_type, int, 0); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)"); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 819bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz/* read/write{8,16} copy_{from,to} routines with window remapping 829bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz * to access whole card 839bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic caddr_t remap_window(struct map_info *map, unsigned long to) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 87cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski struct resource *win = (struct resource *) map->map_priv_2; 88b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski unsigned int offset; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if (!pcmcia_dev_present(dev->p_dev)) { 92e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("device removed\n"); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 96b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski offset = to & ~(dev->win_size-1); 97b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski if (offset != dev->offset) { 98e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n", 99b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski dev->offset, offset); 100b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski ret = pcmcia_map_mem_page(dev->p_dev, win, offset); 1019b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski if (ret != 0) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 103b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski dev->offset = offset; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->win_base + (to & (dev->win_size-1)); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, ofs); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readb(addr); 119e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, ofs); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readw(addr); 134e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long win_size = dev->win_size; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("to = %p from = %lu len = %zd\n", to, from, len); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int toread = win_size - (from & (win_size-1)); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(toread > len) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds toread = len; 15169f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, from); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 156e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(to, addr, toread); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= toread; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += toread; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += toread; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr = remap_window(map, adr); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 172e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n", adr, addr, d.x[0]); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(d.x[0], addr); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr = remap_window(map, adr); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 183e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n", adr, addr, d.x[0]); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(d.x[0], addr); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long win_size = dev->win_size; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 193e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("to = %lu from = %p len = %zd\n", to, from, len); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int towrite = win_size - (to & (win_size-1)); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(towrite > len) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds towrite = len; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, to); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 205e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(addr, from, towrite); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= towrite; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += towrite; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += towrite; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read/write{8,16} copy_{from,to} routines with direct access */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski#define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev))) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read8(struct map_info *map, unsigned long ofs) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readb(win_base + ofs); 227e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", 2289bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz ofs, win_base + ofs, d.x[0]); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read16(struct map_info *map, unsigned long ofs) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readw(win_base + ofs); 242e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", 2439bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz ofs, win_base + ofs, d.x[0]); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 255e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("to = %p from = %lu len = %zd\n", to, from, len); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(to, win_base + from, len); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurzstatic void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 267e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n", 2689bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz adr, win_base + adr, d.x[0]); 269f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurz writeb(d.x[0], win_base + adr); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurzstatic void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 280e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n", 2819bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz adr, win_base + adr, d.x[0]); 282f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurz writew(d.x[0], win_base + adr); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("to = %lu from = %p len = %zd\n", to, from, len); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(win_base + to, from, len); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2987c8d206f219fe52966d970f791246a542718e5baPaul Parsonsstatic DEFINE_SPINLOCK(pcmcia_vpp_lock); 2997c8d206f219fe52966d970f791246a542718e5baPaul Parsonsstatic int pcmcia_vpp_refcnt; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmciamtd_set_vpp(struct map_info *map, int on) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 303fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski struct pcmcia_device *link = dev->p_dev; 3047c8d206f219fe52966d970f791246a542718e5baPaul Parsons unsigned long flags; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 306e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp); 3077c8d206f219fe52966d970f791246a542718e5baPaul Parsons spin_lock_irqsave(&pcmcia_vpp_lock, flags); 3087c8d206f219fe52966d970f791246a542718e5baPaul Parsons if (on) { 3097c8d206f219fe52966d970f791246a542718e5baPaul Parsons if (++pcmcia_vpp_refcnt == 1) /* first nested 'on' */ 3107c8d206f219fe52966d970f791246a542718e5baPaul Parsons pcmcia_fixup_vpp(link, dev->vpp); 3117c8d206f219fe52966d970f791246a542718e5baPaul Parsons } else { 3127c8d206f219fe52966d970f791246a542718e5baPaul Parsons if (--pcmcia_vpp_refcnt == 0) /* last nested 'off' */ 3137c8d206f219fe52966d970f791246a542718e5baPaul Parsons pcmcia_fixup_vpp(link, 0); 3147c8d206f219fe52966d970f791246a542718e5baPaul Parsons } 3157c8d206f219fe52966d970f791246a542718e5baPaul Parsons spin_unlock_irqrestore(&pcmcia_vpp_lock, flags); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 319fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void pcmciamtd_release(struct pcmcia_device *link) 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = link->priv; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 323e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("link = 0x%p\n", link); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 325cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski if (link->resource[2]->end) { 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(dev->win_base) { 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->win_base); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_base = NULL; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 331fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowskistatic int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, 33618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski tuple_t *tuple, 33718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski void *priv_data) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cisparse_t parse; 34069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 34118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (!pcmcia_parse_tuple(tuple, &parse)) { 34218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cistpl_format_t *t = &parse.format; 34318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski (void)t; /* Shut up, gcc */ 344e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n", 34518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski t->type, t->edc, t->offset, t->length); 34618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski } 34718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return -ENOSPC; 34818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski} 34969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 35018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowskistatic int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, 35118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski tuple_t *tuple, 35218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski void *priv_data) 35318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski{ 35418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cisparse_t parse; 35518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski int i; 35669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 35718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (!pcmcia_parse_tuple(tuple, &parse)) { 35818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cistpl_jedec_t *t = &parse.jedec; 35918b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski for (i = 0; i < t->nid; i++) 360e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("JEDEC: 0x%02x 0x%02x\n", 3619bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz t->id[i].mfr, t->id[i].info); 36218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski } 36318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return -ENOSPC; 36418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski} 36569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 36618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowskistatic int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, 36718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski tuple_t *tuple, 36818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski void *priv_data) 36918b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski{ 37018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski struct pcmciamtd_dev *dev = priv_data; 37118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cisparse_t parse; 37218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cistpl_device_t *t = &parse.device; 37318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski int i; 37418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 37518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (pcmcia_parse_tuple(tuple, &parse)) 37618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return -EINVAL; 37718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 378e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Common memory:\n"); 37918b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski dev->pcmcia_map.size = t->dev[0].size; 38018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski /* from here on: DEBUG only */ 38118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski for (i = 0; i < t->ndev; i++) { 382e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Region %d, type = %u\n", i, t->dev[i].type); 383e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp); 384e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed); 385e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size); 38618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski } 38718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return 0; 38818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski} 38969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 39018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowskistatic int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, 39118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski tuple_t *tuple, 39218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski void *priv_data) 39318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski{ 39418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski struct pcmciamtd_dev *dev = priv_data; 39518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cisparse_t parse; 39618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski cistpl_device_geo_t *t = &parse.device_geo; 39718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski int i; 39818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 39918b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (pcmcia_parse_tuple(tuple, &parse)) 40018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return -EINVAL; 40118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 40218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski dev->pcmcia_map.bankwidth = t->geo[0].buswidth; 40318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski /* from here on: DEBUG only */ 40418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski for (i = 0; i < t->ngeo; i++) { 405e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth); 406e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block); 407e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block); 408e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block); 409e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d partition = %u\n", i, t->geo[i].partition); 410e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave); 41118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski } 41218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski return 0; 41318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski} 41469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 41569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 416f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurzstatic void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev, int *new_name) 41718b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski{ 41818b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski int i; 41918b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 42018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (p_dev->prod_id[0]) { 42118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski dev->mtd_name[0] = '\0'; 42218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski for (i = 0; i < 4; i++) { 42318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (i) 42418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski strcat(dev->mtd_name, " "); 42518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski if (p_dev->prod_id[i]) 42618b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski strcat(dev->mtd_name, p_dev->prod_id[i]); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 428e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Found name: %s\n", dev->mtd_name); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43018b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 43118b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL); 43218b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL); 43318b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev); 43418b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev); 43518b61b97294dad74dd00a1aa8efed0cfacb95affDominik Brodowski 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->pcmcia_map.size) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size = MAX_PCMCIA_ADDR; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->pcmcia_map.bankwidth) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.bankwidth = 2; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(force_size) { 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size = force_size << 20; 444e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("size forced to %dM\n", force_size); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(bankwidth) { 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.bankwidth = bankwidth; 449e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("bankwidth forced to %d\n", bankwidth); 45069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner } 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.name = dev->mtd_name; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->mtd_name[0]) { 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(dev->mtd_name, "PCMCIA Memory card"); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *new_name = 1; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 458e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Device: Size: %lu Width:%d Name: %s\n", 4599bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev->pcmcia_map.size, 4609bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev->pcmcia_map.bankwidth << 3, dev->mtd_name); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46415b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int pcmciamtd_config(struct pcmcia_device *link) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = link->priv; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_info *mtd = NULL; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 469cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski int i, j = 0; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static char *probes[] = { "jedec_probe", "cfi_probe" }; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_name = 0; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 473e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("link=0x%p\n", link); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card_settings(dev, link, &new_name); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.phys = NO_XIP; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_from = pcmcia_copy_from_remap; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_to = pcmcia_copy_to_remap; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->pcmcia_map.bankwidth == 1) { 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read8_remap; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write8_remap; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read16_remap; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write16_remap; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(setvpp == 1) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4909bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz /* Request a memory window for PCMCIA. Some architeures can map windows 49125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * up to the maximum that PCMCIA can support (64MiB) - this is ideal and 4929bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz * we aim for a window the size of the whole card - otherwise we try 4939bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz * smaller windows until we succeed 4949bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz */ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 496cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE; 497cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ? 498cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; 499cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->start = 0; 500cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->end = (force_size) ? force_size << 20 : 501cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski MAX_PCMCIA_ADDR; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_size = 0; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 506e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("requesting window with size = %luKiB memspeed = %d\n", 507cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski (unsigned long) resource_size(link->resource[2]) >> 10, 508cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski mem_speed); 509cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ret = pcmcia_request_window(link, link->resource[2], mem_speed); 510e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret) { 512cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski j++; 513cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->start = 0; 514cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->end = (force_size) ? 515cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski force_size << 20 : MAX_PCMCIA_ADDR; 516cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->end >>= j; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 518e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Got window of size %luKiB\n", (unsigned long) 519cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski resource_size(link->resource[2]) >> 10); 520cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski dev->win_size = resource_size(link->resource[2]); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 523cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski } while (link->resource[2]->end >= 0x1000); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 525e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("dev->win_size = %d\n", dev->win_size); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->win_size) { 5289bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n"); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 53015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 532e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10); 53369f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get write protect status */ 535cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski dev->win_base = ioremap(link->resource[2]->start, 536cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski resource_size(link->resource[2])); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->win_base) { 538cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n", 539cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 54115b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 543e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("mapped window dev = %p @ %pR, base = %p\n", 544cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski dev, link->resource[2], dev->win_base); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->offset = 0; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.map_priv_1 = (unsigned long)dev; 548cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2]; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 550f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurz dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(setvpp == 2) { 552e8405f0f617856de0ceb7d04e65b663051451544Dominik Brodowski link->vpp = dev->vpp; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 554e8405f0f617856de0ceb7d04e65b663051451544Dominik Brodowski link->vpp = 0; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5577feabb6412ea23edd298c0fa90e5aa6733eb4a42Dominik Brodowski link->config_index = 0; 558e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Setting Configuration\n"); 5591ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski ret = pcmcia_enable_device(link); 5604c89e88bfde6a3c179790e21004f24e09a058290Dominik Brodowski if (ret != 0) { 56125f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad if (dev->win_base) { 56225f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad iounmap(dev->win_base); 56325f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad dev->win_base = NULL; 56425f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad } 56515b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mem_type == 1) { 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe("map_ram", &dev->pcmcia_map); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if(mem_type == 2) { 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe("map_rom", &dev->pcmcia_map); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 57387d10f3c7954d143e509a2af2bca2a27aeb3114dTobias Klauser for(i = 0; i < ARRAY_SIZE(probes); i++) { 574e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Trying %s\n", probes[i]); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe(probes[i], &dev->pcmcia_map); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd) 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 57869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 579e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("FAILED: %s\n", probes[i]); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 58269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!mtd) { 584e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Can not find an MTD\n"); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 58615b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mtd_info = mtd; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->owner = THIS_MODULE; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(new_name) { 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = 0; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char unit = ' '; 5959bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz /* Since we are using a default name, make it better by adding 5969bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz * in the size 5979bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz */ 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = mtd->size >> 10; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit = 'K'; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = mtd->size >> 20; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit = 'M'; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card"); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the memory found is fits completely into the mapped PCMCIA window, 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use the faster non-remapping read/write functions */ 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd->size <= dev->win_size) { 611e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("Using non remapping memory functions\n"); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->pcmcia_map.bankwidth == 1) { 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read8; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write8; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read16; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write16; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_from = pcmcia_copy_from; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_to = pcmcia_copy_to; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 624ee0e87b174bb41f0310cf089262bf5dd8f95a212Jamie Iles if (mtd_device_register(mtd, NULL, 0)) { 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_destroy(mtd); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mtd_info = NULL; 6279bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev_err(&dev->p_dev->dev, 6289bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz "Could not register the MTD device\n"); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 63015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6329bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); 63315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return 0; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowskistatic int pcmciamtd_suspend(struct pcmcia_device *dev) 63898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 639e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("EVENT_PM_RESUME\n"); 64098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 64198e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski /* get_lock(link); */ 64298e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 64398e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 64498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 64598e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 64698e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowskistatic int pcmciamtd_resume(struct pcmcia_device *dev) 64798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 648e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("EVENT_PM_SUSPEND\n"); 64998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 65098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski /* free_lock(link); */ 65198e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 65298e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 65398e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 65498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 656fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void pcmciamtd_detach(struct pcmcia_device *link) 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 658e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski struct pcmciamtd_dev *dev = link->priv; 659cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski 660e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("link=0x%p\n", link); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 662e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if(dev->mtd_info) { 663ee0e87b174bb41f0310cf089262bf5dd8f95a212Jamie Iles mtd_device_unregister(dev->mtd_info); 6649bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev_info(&dev->p_dev->dev, "mtd%d: Removing\n", 6659bdde162ebcc0237e722e8c3d0d376e35188a98fAlexander Kurz dev->mtd_info->index); 666599fb3298b70d75c12dbdc4dd30f52c5cf04ea2fSean Young map_destroy(dev->mtd_info); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 668e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski 669e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski pcmciamtd_release(link); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int pcmciamtd_probe(struct pcmcia_device *link) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create new memory card device */ 67895b93a0cd46682c6d9e8eea803fda510cb6b863aBurman Yan dev = kzalloc(sizeof(*dev), GFP_KERNEL); 679f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski if (!dev) return -ENOMEM; 680e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug("dev=0x%p\n", dev); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 682fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski dev->p_dev = link; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->priv = dev; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68515b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return pcmciamtd_config(link); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68825f8f54f6e178acfd503a95441b0ea05c525f751Joe Perchesstatic const struct pcmcia_device_id pcmciamtd_ids[] = { 68911d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_FUNC_ID(1), 69011d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21), 69111d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21), 69211d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a), 69311d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e), 69411d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf), 69511d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb), 69611d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c), 69711d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda), 69811d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0), 69911d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), 70011d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), 70111d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), 702f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurz PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965), 703b2321ac37a16f0d6bdbcd2d20263e8b8b943c0eaDominik Brodowski PCMCIA_DEVICE_PROD_ID12("PRETEC", " 2MB SRAM CARD", 0xebf91155, 0x805360ca), 70411d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), 70511d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), 706f6763c98cb2175a816936f9b125d40054a27c185Alexander Kurz PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05), 70711d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), 70811d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), 70911d28a30219671607a235a518f395659599a748eDominik Brodowski /* the following was commented out in pcmcia-cs-3.2.7 */ 71011d28a30219671607a235a518f395659599a748eDominik Brodowski /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */ 71111d28a30219671607a235a518f395659599a748eDominik Brodowski#ifdef CONFIG_MTD_PCMCIA_ANONYMOUS 71211d28a30219671607a235a518f395659599a748eDominik Brodowski { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, }, 71311d28a30219671607a235a518f395659599a748eDominik Brodowski#endif 71411d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_NULL 71511d28a30219671607a235a518f395659599a748eDominik Brodowski}; 71611d28a30219671607a235a518f395659599a748eDominik BrodowskiMODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pcmcia_driver pcmciamtd_driver = { 7192e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski .name = "pcmciamtd", 72015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski .probe = pcmciamtd_probe, 721cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski .remove = pcmciamtd_detach, 72211d28a30219671607a235a518f395659599a748eDominik Brodowski .owner = THIS_MODULE, 72311d28a30219671607a235a518f395659599a748eDominik Brodowski .id_table = pcmciamtd_ids, 72498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .suspend = pcmciamtd_suspend, 72598e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .resume = pcmciamtd_resume, 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_pcmciamtd(void) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(bankwidth && bankwidth != 1 && bankwidth != 2) { 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad bankwidth (%d), using default", bankwidth); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bankwidth = 2; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(force_size && (force_size < 1 || force_size > 64)) { 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad force_size (%d), using default", force_size); 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_size = 0; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mem_type && mem_type != 1 && mem_type != 2) { 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad mem_type (%d), using default", mem_type); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_type = 0; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcmcia_register_driver(&pcmciamtd_driver); 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_pcmciamtd(void) 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 749e6453521edcaa6f130946b5f4fcaf28dbc02f2edBrian Norris pr_debug(DRIVER_DESC " unloading"); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_unregister_driver(&pcmciamtd_driver); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_pcmciamtd); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_pcmciamtd); 755