linux/drivers/net/wireless/b43/pcmcia.c
<<
>>
Prefs
   1/*
   2
   3  Broadcom B43 wireless driver
   4
   5  Copyright (c) 2007 Michael Buesch <m@bues.ch>
   6
   7  This program is free software; you can redistribute it and/or modify
   8  it under the terms of the GNU General Public License as published by
   9  the Free Software Foundation; either version 2 of the License, or
  10  (at your option) any later version.
  11
  12  This program is distributed in the hope that it will be useful,
  13  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  GNU General Public License for more details.
  16
  17  You should have received a copy of the GNU General Public License
  18  along with this program; see the file COPYING.  If not, write to
  19  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  20  Boston, MA 02110-1301, USA.
  21
  22*/
  23
  24#include "pcmcia.h"
  25
  26#include <linux/ssb/ssb.h>
  27#include <linux/slab.h>
  28#include <linux/module.h>
  29
  30#include <pcmcia/cistpl.h>
  31#include <pcmcia/ciscode.h>
  32#include <pcmcia/ds.h>
  33#include <pcmcia/cisreg.h>
  34
  35
  36static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
  37        PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
  38        PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
  39        PCMCIA_DEVICE_NULL,
  40};
  41
  42MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
  43
  44#ifdef CONFIG_PM
  45static int b43_pcmcia_suspend(struct pcmcia_device *dev)
  46{
  47        struct ssb_bus *ssb = dev->priv;
  48
  49        return ssb_bus_suspend(ssb);
  50}
  51
  52static int b43_pcmcia_resume(struct pcmcia_device *dev)
  53{
  54        struct ssb_bus *ssb = dev->priv;
  55
  56        return ssb_bus_resume(ssb);
  57}
  58#else /* CONFIG_PM */
  59# define b43_pcmcia_suspend             NULL
  60# define b43_pcmcia_resume              NULL
  61#endif /* CONFIG_PM */
  62
  63static int b43_pcmcia_probe(struct pcmcia_device *dev)
  64{
  65        struct ssb_bus *ssb;
  66        int err = -ENOMEM;
  67        int res = 0;
  68
  69        ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
  70        if (!ssb)
  71                goto out_error;
  72
  73        err = -ENODEV;
  74
  75        dev->config_flags |= CONF_ENABLE_IRQ;
  76
  77        dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
  78                         WIN_USE_WAIT;
  79        dev->resource[2]->start = 0;
  80        dev->resource[2]->end = SSB_CORE_SIZE;
  81        res = pcmcia_request_window(dev, dev->resource[2], 250);
  82        if (res != 0)
  83                goto err_kfree_ssb;
  84
  85        res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
  86        if (res != 0)
  87                goto err_disable;
  88
  89        if (!dev->irq)
  90                goto err_disable;
  91
  92        res = pcmcia_enable_device(dev);
  93        if (res != 0)
  94                goto err_disable;
  95
  96        err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
  97        if (err)
  98                goto err_disable;
  99        dev->priv = ssb;
 100
 101        return 0;
 102
 103err_disable:
 104        pcmcia_disable_device(dev);
 105err_kfree_ssb:
 106        kfree(ssb);
 107out_error:
 108        printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
 109               res, err);
 110        return err;
 111}
 112
 113static void b43_pcmcia_remove(struct pcmcia_device *dev)
 114{
 115        struct ssb_bus *ssb = dev->priv;
 116
 117        ssb_bus_unregister(ssb);
 118        pcmcia_disable_device(dev);
 119        kfree(ssb);
 120        dev->priv = NULL;
 121}
 122
 123static struct pcmcia_driver b43_pcmcia_driver = {
 124        .owner          = THIS_MODULE,
 125        .name           = "b43-pcmcia",
 126        .id_table       = b43_pcmcia_tbl,
 127        .probe          = b43_pcmcia_probe,
 128        .remove         = b43_pcmcia_remove,
 129        .suspend        = b43_pcmcia_suspend,
 130        .resume         = b43_pcmcia_resume,
 131};
 132
 133/*
 134 * These are not module init/exit functions!
 135 * The module_pcmcia_driver() helper cannot be used here.
 136 */
 137int b43_pcmcia_init(void)
 138{
 139        return pcmcia_register_driver(&b43_pcmcia_driver);
 140}
 141
 142void b43_pcmcia_exit(void)
 143{
 144        pcmcia_unregister_driver(&b43_pcmcia_driver);
 145}
 146