sl811_cs.c revision 325a4af60dc945bf2da9cbcdbabb276e312b297c
1c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/* 2c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * PCMCIA driver for SL811HS (as found in REX-CFU1U) 3c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Filename: sl811_cs.c 4c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Author: Yukio Yamamoto 5c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * 6c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Port to sl811-hcd and 2.6.x by 7c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Botond Botyanszki <boti@rocketmail.com> 8c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Simon Pickering 9c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * 10c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell * Last update: 2005-05-12 11c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell */ 12c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 13c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/kernel.h> 14c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/module.h> 15c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/init.h> 16c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/sched.h> 17c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/ptrace.h> 18c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/slab.h> 19c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/string.h> 20c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/timer.h> 21c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <linux/ioport.h> 22d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 23c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 24c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <pcmcia/cs_types.h> 25c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <pcmcia/cs.h> 26c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <pcmcia/cistpl.h> 27c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <pcmcia/cisreg.h> 28c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#include <pcmcia/ds.h> 29c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 30325a4af60dc945bf2da9cbcdbabb276e312b297cDavid Brownell#include <linux/usb/sl811.h> 31c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 32c6de2b64eb575a3f9326969ec5fcdc6032b38e42David BrownellMODULE_AUTHOR("Botond Botyanszki"); 33c6de2b64eb575a3f9326969ec5fcdc6032b38e42David BrownellMODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); 34c6de2b64eb575a3f9326969ec5fcdc6032b38e42David BrownellMODULE_LICENSE("GPL"); 35c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 36c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 37c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 38c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/* MACROS */ 39c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 40c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 41c9a50cc9318772e62d56f2a9172bdfda72bdacbeDavid Brownell#if defined(DEBUG) || defined(PCMCIA_DEBUG) 42c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 43c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic int pc_debug = 0; 44c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellmodule_param(pc_debug, int, 0644); 45c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 46c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args) 47c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 48c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#else 49c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#define DBG(n, args...) do{}while(0) 50c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#endif /* no debugging */ 51c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 52c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#define INFO(args...) printk(KERN_INFO "sl811_cs: " args) 53c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 54c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) 55c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 56c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell#define CS_CHECK(fn, ret) \ 57c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell do { \ 58c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell last_fn = (fn); \ 59c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if ((last_ret = (ret)) != 0) \ 60c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto cs_failed; \ 61c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } while (0) 62c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 63c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 64c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/* VARIABLES */ 65c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 66c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 67c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic const char driver_name[DEV_NAME_LEN] = "sl811_cs"; 68c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 69c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownelltypedef struct local_info_t { 70fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski struct pcmcia_device *p_dev; 71c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell dev_node_t node; 72c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} local_info_t; 73c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 74fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void sl811_cs_release(struct pcmcia_device * link); 75cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski 76c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 77c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 78c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic void release_platform_dev(struct device * dev) 79c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 80c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell DBG(0, "sl811_cs platform_dev release\n"); 81c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell dev->parent = NULL; 82c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 83c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 84c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic struct sl811_platform_data platform_data = { 85c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .potpg = 100, 86c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .power = 50, /* == 100mA */ 87c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell // .reset = ... FIXME: invoke CF reset on the card 88c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell}; 89c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 90c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic struct resource resources[] = { 91c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell [0] = { 92c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .flags = IORESOURCE_IRQ, 93c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell }, 94c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell [1] = { 95c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell // .name = "address", 96c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .flags = IORESOURCE_IO, 97c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell }, 98c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell [2] = { 99c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell // .name = "data", 100c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .flags = IORESOURCE_IO, 101c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell }, 102c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell}; 103c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 104a0c53f1dca10acc93462339cbd0bf24b10d60a13David Brownellextern struct platform_driver sl811h_driver; 105c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 106c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic struct platform_device platform_dev = { 107c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .id = -1, 108c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .dev = { 109c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .platform_data = &platform_data, 110c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .release = release_platform_dev, 111c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell }, 112c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .resource = resources, 113c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .num_resources = ARRAY_SIZE(resources), 114c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell}; 115c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 116c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) 117c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 118c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (platform_dev.dev.parent) 119c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell return -EBUSY; 120c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell platform_dev.dev.parent = parent; 121c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 122c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* finish seting up the platform device */ 123c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell resources[0].start = irq; 124c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 125c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell resources[1].start = base_addr; 126c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell resources[1].end = base_addr; 127c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 128c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell resources[2].start = base_addr + 1; 129c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell resources[2].end = base_addr + 1; 130c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 131c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* The driver core will probe for us. We know sl811-hcd has been 132c9a50cc9318772e62d56f2a9172bdfda72bdacbeDavid Brownell * initialized already because of the link order dependency created 133c9a50cc9318772e62d56f2a9172bdfda72bdacbeDavid Brownell * by referencing "sl811h_driver". 134c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell */ 135a0c53f1dca10acc93462339cbd0bf24b10d60a13David Brownell platform_dev.name = sl811h_driver.driver.name; 136c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell return platform_device_register(&platform_dev); 137c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 138c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 139c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 140c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 141fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void sl811_cs_detach(struct pcmcia_device *link) 142c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 143c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell DBG(0, "sl811_cs_detach(0x%p)\n", link); 144c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 145e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski sl811_cs_release(link); 146c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 147c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* This points to the parent local_info_t struct */ 148c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell kfree(link->priv); 149c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 150c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 151fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void sl811_cs_release(struct pcmcia_device * link) 152c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 153c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell DBG(0, "sl811_cs_release(0x%p)\n", link); 154c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 155fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 156c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell platform_device_unregister(&platform_dev); 157c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 158c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 15915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int sl811_cs_config(struct pcmcia_device *link) 160c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 161fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski struct device *parent = &handle_to_dev(link); 162c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell local_info_t *dev = link->priv; 163c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple_t tuple; 164c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell cisparse_t parse; 165c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell int last_fn, last_ret; 166c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell u_char buf[64]; 167c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell config_info_t conf; 168c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell cistpl_cftable_entry_t dflt = { 0 }; 169c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 170c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell DBG(0, "sl811_cs_config(0x%p)\n", link); 171c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 172c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.DesiredTuple = CISTPL_CONFIG; 173c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.Attributes = 0; 174c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.TupleData = buf; 175c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.TupleDataMax = sizeof(buf); 176c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.TupleOffset = 0; 177fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 178fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); 179fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); 180c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.ConfigBase = parse.config.base; 181c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.Present = parse.config.rmask[0]; 182c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 183c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* Look up the current Vcc */ 184c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell CS_CHECK(GetConfigurationInfo, 185fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_get_configuration_info(link, &conf)); 186c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 187c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 188fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 189c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell while (1) { 190c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); 191c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 192fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski if (pcmcia_get_tuple_data(link, &tuple) != 0 193fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski || pcmcia_parse_tuple(link, &tuple, &parse) 194c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell != 0) 195c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto next_entry; 196c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 197c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { 198c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell dflt = *cfg; 199c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } 200c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 201c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->index == 0) 202c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto next_entry; 203c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 204c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.ConfigIndex = cfg->index; 205c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 206c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* Use power settings for Vcc and Vpp if present */ 207c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* Note that the CIS values need to be rescaled */ 208c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { 209c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 210c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell != conf.Vcc) 211c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto next_entry; 212c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { 213c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000 214c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell != conf.Vcc) 215c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto next_entry; 216c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } 217c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 218c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) 21970294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski link->conf.Vpp = 220c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; 221c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) 22270294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski link->conf.Vpp = 223c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; 224c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 225c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* we need an interrupt */ 226c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) 227c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.Attributes |= CONF_ENABLE_IRQ; 228c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 229c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* IO window settings */ 230c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.NumPorts1 = link->io.NumPorts2 = 0; 231c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { 232c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; 233c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 234c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; 235c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; 236c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.BasePort1 = io->win[0].base; 237c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.NumPorts1 = io->win[0].len; 238c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 239fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski if (pcmcia_request_io(link, &link->io) != 0) 240c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto next_entry; 241c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } 242c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell break; 243c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 244c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellnext_entry: 245fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 246fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski last_ret = pcmcia_get_next_tuple(link, &tuple); 247c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } 248c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 249c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* require an IRQ and two registers */ 250c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) 251c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto cs_failed; 252c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (link->conf.Attributes & CONF_ENABLE_IRQ) 253c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell CS_CHECK(RequestIRQ, 254fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_request_irq(link, &link->irq)); 255c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell else 256c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell goto cs_failed; 257c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 258c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell CS_CHECK(RequestConfiguration, 259fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_request_configuration(link, &link->conf)); 260c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 261c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell sprintf(dev->node.dev_name, driver_name); 262c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell dev->node.major = dev->node.minor = 0; 263fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski link->dev_node = &dev->node; 264c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 26570294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski printk(KERN_INFO "%s: index 0x%02x: ", 26670294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski dev->node.dev_name, link->conf.ConfigIndex); 26770294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski if (link->conf.Vpp) 26870294b468302fd7a0a99dad935c7ba5322989345Dominik Brodowski printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); 269c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell printk(", irq %d", link->irq.AssignedIRQ); 270c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell printk(", io 0x%04x-0x%04x", link->io.BasePort1, 271c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->io.BasePort1+link->io.NumPorts1-1); 272c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell printk("\n"); 273c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 274c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) 275c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell < 0) { 276c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellcs_failed: 277c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell printk("sl811_cs_config failed\n"); 278fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski cs_error(link, last_fn, last_ret); 279c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell sl811_cs_release(link); 28015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 281c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell } 28215b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return 0; 283c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 284c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 28515b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int sl811_cs_probe(struct pcmcia_device *link) 286c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 287c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell local_info_t *local; 288c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 289c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell local = kmalloc(sizeof(local_info_t), GFP_KERNEL); 290c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell if (!local) 291f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski return -ENOMEM; 292c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell memset(local, 0, sizeof(local_info_t)); 293fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski local->p_dev = link; 294c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->priv = local; 295c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 296c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell /* Initialize */ 297c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 298c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; 299c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->irq.Handler = NULL; 300c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 301c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.Attributes = 0; 302c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell link->conf.IntType = INT_MEMORY_AND_IO; 303c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 30415b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return sl811_cs_config(link); 305c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 306c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 30722f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownellstatic struct pcmcia_device_id sl811_ids[] = { 30822f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownell PCMCIA_DEVICE_MANF_CARD(0xc015, 0x0001), /* RATOC USB HOST CF+ Card */ 30922f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownell PCMCIA_DEVICE_NULL, 31022f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownell}; 31122f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid BrownellMODULE_DEVICE_TABLE(pcmcia, sl811_ids); 31222f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownell 313c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic struct pcmcia_driver sl811_cs_driver = { 314c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .owner = THIS_MODULE, 315c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .drv = { 316c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell .name = (char *)driver_name, 317c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell }, 31815b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski .probe = sl811_cs_probe, 319cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski .remove = sl811_cs_detach, 32022f3a8f5fc94be4dd31c4c5ec1d1dc2b9c83a8acDavid Brownell .id_table = sl811_ids, 321c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell}; 322c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 323c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell/*====================================================================*/ 324c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 325c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic int __init init_sl811_cs(void) 326c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 327c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell return pcmcia_register_driver(&sl811_cs_driver); 328c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 329c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellmodule_init(init_sl811_cs); 330c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell 331c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellstatic void __exit exit_sl811_cs(void) 332c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell{ 333c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell pcmcia_unregister_driver(&sl811_cs_driver); 334c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownell} 335c6de2b64eb575a3f9326969ec5fcdc6032b38e42David Brownellmodule_exit(exit_sl811_cs); 336