pcmciamtd.c revision 25f0c659fe64832d8ee06aa623fffaad708dcf8b
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner * $Id: pcmciamtd.c,v 1.55 2005/11/07 11:14:28 gleixner Exp $ 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pcmciamtd.c - MTD driver for PCMCIA flash memory cards 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Simon Evans <spse@secret.org.uk> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Simon Evans 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licence: GPL 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs_types.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ds.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MTD_DEBUG 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = CONFIG_MTD_DEBUG_VERBOSE; 318d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(debug, int, 0); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG(n, format, arg...) \ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n <= debug) { \ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG(n, arg...) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const int debug = 0; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg) 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_DESC "PCMCIA Flash memory card driver" 5169f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner#define DRIVER_VERSION "$Revision: 1.55 $" 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Size of the PCMCIA address space: 26 bits = 64 MB */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PCMCIA_ADDR 0x4000000 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pcmciamtd_dev { 57fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski struct pcmcia_device *p_dev; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_node_t node; /* device node */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base; /* ioremapped address of PCMCIA window */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int win_size; /* size of window */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int offset; /* offset into card the window currently points at */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct map_info pcmcia_map; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_info *mtd_info; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vpp; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char mtd_name[sizeof(struct cistpl_vers_1_t)]; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Module parameters */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bankwidth = 2; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Speed of memory accesses, in ns */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mem_speed; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force the size of an SRAM card */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int force_size; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force Vpp */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int vpp; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set Vpp */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int setvpp; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force card to be treated as FLASH, ROM or RAM */ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mem_type; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(DRIVER_DESC); 928d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(bankwidth, int, 0); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)"); 948d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(mem_speed, int, 0); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); 968d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(force_size, int, 0); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); 988d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(setvpp, int, 0); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); 1008d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(vpp, int, 0); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)"); 1028d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(mem_type, int, 0); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)"); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic caddr_t remap_window(struct map_info *map, unsigned long to) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds window_handle_t win = (window_handle_t)map->map_priv_2; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memreq_t mrq; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 114e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if (!pcmcia_dev_present(dev->p_dev)) { 115e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski DEBUG(1, "device removed"); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq.CardOffset = to & ~(dev->win_size-1); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mrq.CardOffset != dev->offset) { 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->offset, mrq.CardOffset); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mrq.Page = 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { 125fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(dev->p_dev, MapMemPage, ret); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->offset = mrq.CardOffset; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev->win_base + (to & (dev->win_size-1)); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, ofs); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readb(addr); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, ofs); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readw(addr); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long win_size = dev->win_size; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "to = %p from = %lu len = %u", to, from, len); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int toread = win_size - (from & (win_size-1)); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(toread > len) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds toread = len; 17669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, from); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(to, addr, toread); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= toread; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += toread; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += toread; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr = remap_window(map, adr); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(d.x[0], addr); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr = remap_window(map, adr); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(d.x[0], addr); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long win_size = dev->win_size; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "to = %lu from = %p len = %u", to, from, len); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(len) { 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int towrite = win_size - (to & (win_size-1)); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t addr; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(towrite > len) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds towrite = len; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = remap_window(map, to); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!addr) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(addr, from, towrite); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= towrite; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to += towrite; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from += towrite; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read/write{8,16} copy_{from,to} routines with direct access */ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski#define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev))) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read8(struct map_info *map, unsigned long ofs) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readb(win_base + ofs); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]); 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word pcmcia_read16(struct map_info *map, unsigned long ofs) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word d = {{0}}; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d.x[0] = readw(win_base + ofs); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return d; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "to = %p from = %lu len = %u", to, from, len); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(to, win_base + from, len); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(d, win_base + adr); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writew(d, win_base + adr); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds caddr_t win_base = (caddr_t)map->map_priv_2; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(DEV_REMOVED(map)) 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "to = %lu from = %p len = %u", to, from, len); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(win_base + to, from, len); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcmciamtd_set_vpp(struct map_info *map, int on) 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; 322fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski struct pcmcia_device *link = dev->p_dev; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modconf_t mod; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod.Vcc = 0; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); 331fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski ret = pcmcia_modify_configuration(link, &mod); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret != CS_SUCCESS) { 333fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, ModifyConfiguration, ret); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* After a card is removed, pcmciamtd_release() will unregister the 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device, and release the PCMCIA configuration. If the device is 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * still open, this will be postponed until it is closed. 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 343fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void pcmciamtd_release(struct pcmcia_device *link) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = link->priv; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "link = 0x%p", link); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (link->win) { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(dev->win_base) { 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->win_base); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_base = NULL; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_release_window(link->win); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 356fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 360fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple_t tuple; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cisparse_t parse; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char buf[64]; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple.Attributes = 0; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple.TupleData = (cisdata_t *)buf; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple.TupleDataMax = sizeof(buf); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple.TupleOffset = 0; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tuple.DesiredTuple = RETURN_FIRST_TUPLE; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 373fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski rc = pcmcia_get_first_tuple(link, &tuple); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(rc == CS_SUCCESS) { 375fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski rc = pcmcia_get_tuple_data(link, &tuple); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(rc != CS_SUCCESS) { 377fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, GetTupleData, rc); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 380fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski rc = pcmcia_parse_tuple(link, &tuple, &parse); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(rc != CS_SUCCESS) { 382fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, ParseTuple, rc); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 38569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(tuple.TupleCode) { 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CISTPL_FORMAT: { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cistpl_format_t *t = &parse.format; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void)t; /* Shut up, gcc */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->type, t->edc, t->offset, t->length); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 39369f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 39569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CISTPL_DEVICE: { 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cistpl_device_t *t = &parse.device; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Common memory:"); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size = t->dev[0].size; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < t->ndev; i++) { 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 40969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CISTPL_VERS_1: { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cistpl_vers_1_t *t = &parse.version_1; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(t->ns) { 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mtd_name[0] = '\0'; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < t->ns; i++) { 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(dev->mtd_name, " "); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(dev->mtd_name, t->str+t->ofs[i]); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Found name: %s", dev->mtd_name); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 42469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CISTPL_JEDEC_C: { 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cistpl_jedec_t *t = &parse.jedec; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < t->nid; i++) { 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 43369f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CISTPL_DEVICE_GEO: { 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cistpl_device_geo_t *t = &parse.device_geo; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.bankwidth = t->geo[0].buswidth; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < t->ngeo; i++) { 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 44869f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 45269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 453fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski rc = pcmcia_get_next_tuple(link, &tuple); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->pcmcia_map.size) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size = MAX_PCMCIA_ADDR; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->pcmcia_map.bankwidth) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.bankwidth = 2; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(force_size) { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size = force_size << 20; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "size forced to %dM", force_size); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(bankwidth) { 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.bankwidth = bankwidth; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "bankwidth forced to %d", bankwidth); 46969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner } 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.name = dev->mtd_name; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->mtd_name[0]) { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(dev->mtd_name, "PCMCIA Memory card"); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *new_name = 1; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "Device: Size: %lu Width:%d Name: %s", 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is received, to configure the PCMCIA socket, and to make the 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MTD device available to the system. 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CS_CHECK(fn, ret) \ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int pcmciamtd_config(struct pcmcia_device *link) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev = link->priv; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_info *mtd = NULL; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs_status_t status; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds win_req_t req; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int last_ret = 0, last_fn = 0; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds config_info_t t; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static char *probes[] = { "jedec_probe", "cfi_probe" }; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cisinfo_t cisinfo; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int new_name = 0; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "link=0x%p", link); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Validating CIS"); 507fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski ret = pcmcia_validate_cis(link, &cisinfo); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret != CS_SUCCESS) { 509fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, GetTupleData, ret); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card_settings(dev, link, &new_name); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.phys = NO_XIP; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_from = pcmcia_copy_from_remap; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_to = pcmcia_copy_to_remap; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->pcmcia_map.bankwidth == 1) { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read8_remap; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write8_remap; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read16_remap; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write16_remap; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(setvpp == 1) 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds whole card - otherwise we try smaller windows until we succeed */ 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Base = 0; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.AccessSpeed = mem_speed; 537fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski link->win = (window_handle_t)link; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_size = 0; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "requesting window with size = %dKiB memspeed = %d", 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Size >> 10, req.AccessSpeed); 545fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski ret = pcmcia_request_window(&link, &req, &link->win); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret) { 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req.Size >>= 1; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Got window of size %dKiB", req.Size >> 10); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_size = req.Size; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while(req.Size >= 0x1000); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "dev->win_size = %d", dev->win_size); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->win_size) { 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("Cant allocate memory window"); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 56115b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); 56469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get write protect status */ 566fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(GetStatus, pcmcia_get_status(link, &status)); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status.CardState, (unsigned long)link->win); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->win_base = ioremap(req.Base, req.Size); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev->win_base) { 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("ioremap(%lu, %u) failed", req.Base, req.Size); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 57315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev, req.Base, dev->win_base, req.Size); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->offset = 0; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.map_priv_1 = (unsigned long)dev; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Getting configuration"); 583fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t)); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->vpp = (vpp) ? vpp : t.Vpp1; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Attributes = 0; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(setvpp == 2) { 58870294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski link->conf.Vpp = dev->vpp; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 59070294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski link->conf.Vpp = 0; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.IntType = INT_MEMORY; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.ConfigBase = t.ConfigBase; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Status = t.Status; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Pin = t.Pin; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Copy = t.Copy; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.ExtStatus = t.ExtStatus; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.ConfigIndex = 0; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Present = t.Present; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(2, "Setting Configuration"); 602fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski ret = pcmcia_request_configuration(link, &link->conf); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(ret != CS_SUCCESS) { 604fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, RequestConfiguration, ret); 60525f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad if (dev->win_base) { 60625f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad iounmap(dev->win_base); 60725f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad dev->win_base = NULL; 60825f0c659fe64832d8ee06aa623fffaad708dcf8bAmol Lad } 60915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mem_type == 1) { 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe("map_ram", &dev->pcmcia_map); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if(mem_type == 2) { 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe("map_rom", &dev->pcmcia_map); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 61787d10f3c7954d143e509a2af2bca2a27aeb3114dTobias Klauser for(i = 0; i < ARRAY_SIZE(probes); i++) { 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "Trying %s", probes[i]); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = do_map_probe(probes[i], &dev->pcmcia_map); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd) 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 62269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "FAILED: %s", probes[i]); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 62669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!mtd) { 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "Cant find an MTD"); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 63015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mtd_info = mtd; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->owner = THIS_MODULE; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(new_name) { 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = 0; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char unit = ' '; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Since we are using a default name, make it better by adding in the 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size */ 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = mtd->size >> 10; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit = 'K'; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = mtd->size >> 20; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unit = 'M'; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card"); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the memory found is fits completely into the mapped PCMCIA window, 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds use the faster non-remapping read/write functions */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mtd->size <= dev->win_size) { 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "Using non remapping memory functions"); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->pcmcia_map.bankwidth == 1) { 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read8; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write8; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.read = pcmcia_read16; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.write = pcmcia_write16; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_from = pcmcia_copy_from; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->pcmcia_map.copy_to = pcmcia_copy_to; 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(add_mtd_device(mtd)) { 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_destroy(mtd); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->mtd_info = NULL; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("Couldnt register MTD device"); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 67215b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("mtd%d: %s", mtd->index, mtd->name); 676fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski link->dev_node = &dev->node; 67715b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return 0; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs_failed: 680fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, last_fn, last_ret); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err("CS Error, exiting"); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmciamtd_release(link); 68315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowskistatic int pcmciamtd_suspend(struct pcmcia_device *dev) 68898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 68998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski DEBUG(2, "EVENT_PM_RESUME"); 69098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 69198e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski /* get_lock(link); */ 69298e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 69398e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 69498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 69598e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 69698e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowskistatic int pcmciamtd_resume(struct pcmcia_device *dev) 69798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 69898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski DEBUG(2, "EVENT_PM_SUSPEND"); 69998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 70098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski /* free_lock(link); */ 70198e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 70298e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 70398e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 70498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This deletes a driver "instance". The device is de-registered 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with Card Services. If it has been released, all local data 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * structures are freed. Otherwise, the structures will be freed 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when the device is released. 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 712fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void pcmciamtd_detach(struct pcmcia_device *link) 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 714e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski struct pcmciamtd_dev *dev = link->priv; 715cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(3, "link=0x%p", link); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 718e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if(dev->mtd_info) { 719e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski del_mtd_device(dev->mtd_info); 720599fb3298b70d75c12dbdc4dd30f52c5cf04ea2fSean Young map_destroy(dev->mtd_info); 721e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski info("mtd%d: Removed", dev->mtd_info->index); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 723e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski 724e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski pcmciamtd_release(link); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* pcmciamtd_attach() creates an "instance" of the driver, allocating 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * local data structures for one device. The device is registered 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with Card Services. 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int pcmciamtd_probe(struct pcmcia_device *link) 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcmciamtd_dev *dev; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create new memory card device */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = kmalloc(sizeof(*dev), GFP_KERNEL); 739f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski if (!dev) return -ENOMEM; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, "dev=0x%p", dev); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(dev, 0, sizeof(*dev)); 743fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski dev->p_dev = link; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->priv = dev; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.Attributes = 0; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->conf.IntType = INT_MEMORY; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return pcmciamtd_config(link); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 75211d28a30219671607a235a518f395659599a748eDominik Brodowskistatic struct pcmcia_device_id pcmciamtd_ids[] = { 75311d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_FUNC_ID(1), 75411d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21), 75511d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21), 75611d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a), 75711d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e), 75811d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf), 75911d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb), 76011d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c), 76111d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda), 76211d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0), 76311d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), 76411d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), 76511d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), 76611d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), 76711d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), 76811d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), 76911d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), 77011d28a30219671607a235a518f395659599a748eDominik Brodowski /* the following was commented out in pcmcia-cs-3.2.7 */ 77111d28a30219671607a235a518f395659599a748eDominik Brodowski /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */ 77211d28a30219671607a235a518f395659599a748eDominik Brodowski#ifdef CONFIG_MTD_PCMCIA_ANONYMOUS 77311d28a30219671607a235a518f395659599a748eDominik Brodowski { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, }, 77411d28a30219671607a235a518f395659599a748eDominik Brodowski#endif 77511d28a30219671607a235a518f395659599a748eDominik Brodowski PCMCIA_DEVICE_NULL 77611d28a30219671607a235a518f395659599a748eDominik Brodowski}; 77711d28a30219671607a235a518f395659599a748eDominik BrodowskiMODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pcmcia_driver pcmciamtd_driver = { 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drv = { 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "pcmciamtd" 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 78315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski .probe = pcmciamtd_probe, 784cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski .remove = pcmciamtd_detach, 78511d28a30219671607a235a518f395659599a748eDominik Brodowski .owner = THIS_MODULE, 78611d28a30219671607a235a518f395659599a748eDominik Brodowski .id_table = pcmciamtd_ids, 78798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .suspend = pcmciamtd_suspend, 78898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .resume = pcmciamtd_resume, 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_pcmciamtd(void) 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info(DRIVER_DESC " " DRIVER_VERSION); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(bankwidth && bankwidth != 1 && bankwidth != 2) { 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad bankwidth (%d), using default", bankwidth); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bankwidth = 2; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(force_size && (force_size < 1 || force_size > 64)) { 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad force_size (%d), using default", force_size); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_size = 0; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mem_type && mem_type != 1 && mem_type != 2) { 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info("bad mem_type (%d), using default", mem_type); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_type = 0; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcmcia_register_driver(&pcmciamtd_driver); 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_pcmciamtd(void) 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG(1, DRIVER_DESC " unloading"); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_unregister_driver(&pcmciamtd_driver); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_pcmciamtd); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_pcmciamtd); 820