diff options
Diffstat (limited to 'drivers/usb/host/sl811_cs.c')
| -rw-r--r-- | drivers/usb/host/sl811_cs.c | 290 |
1 files changed, 52 insertions, 238 deletions
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 466384d7c79..88a9bffe93d 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -12,8 +12,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> #include <linux/ptrace.h> #include <linux/slab.h> #include <linux/string.h> @@ -21,13 +19,11 @@ #include <linux/ioport.h> #include <linux/platform_device.h> -#include <pcmcia/cs_types.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> -#include <linux/usb_sl811.h> +#include <linux/usb/sl811.h> MODULE_AUTHOR("Botond Botyanszki"); MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); @@ -38,46 +34,23 @@ MODULE_LICENSE("GPL"); /* MACROS */ /*====================================================================*/ -#if defined(DEBUG) || defined(PCMCIA_DEBUG) - -static int pc_debug = 0; -module_param(pc_debug, int, 0644); - -#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args) - -#else -#define DBG(n, args...) do{}while(0) -#endif /* no debugging */ - #define INFO(args...) printk(KERN_INFO "sl811_cs: " args) -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) - -#define CS_CHECK(fn, ret) \ - do { \ - last_fn = (fn); \ - if ((last_ret = (ret)) != 0) \ - goto cs_failed; \ - } while (0) - /*====================================================================*/ /* VARIABLES */ /*====================================================================*/ -static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; - typedef struct local_info_t { - dev_link_t link; - dev_node_t node; + struct pcmcia_device *p_dev; } local_info_t; -static void sl811_cs_release(dev_link_t * link); +static void sl811_cs_release(struct pcmcia_device * link); /*====================================================================*/ static void release_platform_dev(struct device * dev) { - DBG(0, "sl811_cs platform_dev release\n"); + dev_dbg(dev, "sl811_cs platform_dev release\n"); dev->parent = NULL; } @@ -101,7 +74,7 @@ static struct resource resources[] = { }, }; -extern struct device_driver sl811h_driver; +extern struct platform_driver sl811h_driver; static struct platform_device platform_dev = { .id = -1, @@ -113,7 +86,8 @@ static struct platform_device platform_dev = { .num_resources = ARRAY_SIZE(resources), }; -static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) +static int sl811_hc_init(struct device *parent, resource_size_t base_addr, + int irq) { if (platform_dev.dev.parent) return -EBUSY; @@ -132,230 +106,87 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) * initialized already because of the link order dependency created * by referencing "sl811h_driver". */ - platform_dev.name = sl811h_driver.name; + platform_dev.name = sl811h_driver.driver.name; return platform_device_register(&platform_dev); } /*====================================================================*/ -static void sl811_cs_detach(struct pcmcia_device *p_dev) +static void sl811_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); + dev_dbg(&link->dev, "sl811_cs_detach\n"); - DBG(0, "sl811_cs_detach(0x%p)\n", link); - - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - sl811_cs_release(link); + sl811_cs_release(link); /* This points to the parent local_info_t struct */ kfree(link->priv); } -static void sl811_cs_release(dev_link_t * link) +static void sl811_cs_release(struct pcmcia_device * link) { + dev_dbg(&link->dev, "sl811_cs_release\n"); - DBG(0, "sl811_cs_release(0x%p)\n", link); - - /* Unlink the device chain */ - link->dev = NULL; - + pcmcia_disable_device(link); platform_device_unregister(&platform_dev); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; } -static void sl811_cs_config(dev_link_t *link) +static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) { - client_handle_t handle = link->handle; - struct device *parent = &handle_to_dev(handle); - local_info_t *dev = link->priv; - tuple_t tuple; - cisparse_t parse; - int last_fn, last_ret; - u_char buf[64]; - config_info_t conf; - cistpl_cftable_entry_t dflt = { 0 }; - - DBG(0, "sl811_cs_config(0x%p)\n", link); - - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - while (1) { - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - - if (pcmcia_get_tuple_data(handle, &tuple) != 0 - || pcmcia_parse_tuple(handle, &tuple, &parse) - != 0) - goto next_entry; - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { - dflt = *cfg; - } - - if (cfg->index == 0) - goto next_entry; - - link->conf.ConfigIndex = cfg->index; - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 - != conf.Vcc) - goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000 - != conf.Vcc) - goto next_entry; - } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* we need an interrupt */ - if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - - if (pcmcia_request_io(link->handle, &link->io) != 0) - goto next_entry; - } - break; - -next_entry: - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - last_ret = pcmcia_get_next_tuple(handle, &tuple); - } + if (p_dev->config_index == 0) + return -EINVAL; - /* require an IRQ and two registers */ - if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) - goto cs_failed; - if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, - pcmcia_request_irq(link->handle, &link->irq)); - else - goto cs_failed; - - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link->handle, &link->conf)); - - sprintf(dev->node.dev_name, driver_name); - dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; - - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); - printk(", irq %d", link->irq.AssignedIRQ); - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; - - if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) - < 0) { -cs_failed: - printk("sl811_cs_config failed\n"); - cs_error(link->handle, last_fn, last_ret); - sl811_cs_release(link); - link->state &= ~DEV_CONFIG_PENDING; - } + return pcmcia_request_io(p_dev); } -static int sl811_suspend(struct pcmcia_device *dev) + +static int sl811_cs_config(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); + struct device *parent = &link->dev; + int ret; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); + dev_dbg(&link->dev, "sl811_cs_config\n"); - return 0; -} + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | + CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO; -static int sl811_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); + if (pcmcia_loop_config(link, sl811_cs_config_check, NULL)) + goto failed; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); + /* require an IRQ and two registers */ + if (resource_size(link->resource[0]) < 2) + goto failed; + + if (!link->irq) + goto failed; + + ret = pcmcia_enable_device(link); + if (ret) + goto failed; + if (sl811_hc_init(parent, link->resource[0]->start, link->irq) + < 0) { +failed: + printk(KERN_WARNING "sl811_cs_config failed\n"); + sl811_cs_release(link); + return -ENODEV; + } return 0; } -static int sl811_cs_attach(struct pcmcia_device *p_dev) +static int sl811_cs_probe(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link; - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); - link = &local->link; + local->p_dev = link; link->priv = local; - /* Initialize */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - link->irq.Handler = NULL; - - link->conf.Attributes = 0; - link->conf.Vcc = 33; - link->conf.IntType = INT_MEMORY_AND_IO; - - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - sl811_cs_config(link); - - return 0; + return sl811_cs_config(link); } -static struct pcmcia_device_id sl811_ids[] = { +static const struct pcmcia_device_id sl811_ids[] = { PCMCIA_DEVICE_MANF_CARD(0xc015, 0x0001), /* RATOC USB HOST CF+ Card */ PCMCIA_DEVICE_NULL, }; @@ -363,26 +194,9 @@ MODULE_DEVICE_TABLE(pcmcia, sl811_ids); static struct pcmcia_driver sl811_cs_driver = { .owner = THIS_MODULE, - .drv = { - .name = (char *)driver_name, - }, - .probe = sl811_cs_attach, + .name = "sl811_cs", + .probe = sl811_cs_probe, .remove = sl811_cs_detach, .id_table = sl811_ids, - .suspend = sl811_suspend, - .resume = sl811_resume, }; - -/*====================================================================*/ - -static int __init init_sl811_cs(void) -{ - return pcmcia_register_driver(&sl811_cs_driver); -} -module_init(init_sl811_cs); - -static void __exit exit_sl811_cs(void) -{ - pcmcia_unregister_driver(&sl811_cs_driver); -} -module_exit(exit_sl811_cs); +module_pcmcia_driver(sl811_cs_driver); |
