linux/drivers/net/wireless/b43/pcmcia.c
<<
>>
Prefs
   1/*
   2
   3  Broadcom B43 wireless driver
   4
   5  Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
   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
  28#include <pcmcia/cs_types.h>
  29#include <pcmcia/cs.h>
  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 __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
  64{
  65        struct ssb_bus *ssb;
  66        win_req_t win;
  67        memreq_t mem;
  68        tuple_t tuple;
  69        cisparse_t parse;
  70        int err = -ENOMEM;
  71        int res = 0;
  72        unsigned char buf[64];
  73
  74        ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
  75        if (!ssb)
  76                goto out_error;
  77
  78        err = -ENODEV;
  79        tuple.DesiredTuple = CISTPL_CONFIG;
  80        tuple.Attributes = 0;
  81        tuple.TupleData = buf;
  82        tuple.TupleDataMax = sizeof(buf);
  83        tuple.TupleOffset = 0;
  84
  85        res = pcmcia_get_first_tuple(dev, &tuple);
  86        if (res != 0)
  87                goto err_kfree_ssb;
  88        res = pcmcia_get_tuple_data(dev, &tuple);
  89        if (res != 0)
  90                goto err_kfree_ssb;
  91        res = pcmcia_parse_tuple(&tuple, &parse);
  92        if (res != 0)
  93                goto err_kfree_ssb;
  94
  95        dev->conf.ConfigBase = parse.config.base;
  96        dev->conf.Present = parse.config.rmask[0];
  97        dev->conf.Attributes = CONF_ENABLE_IRQ;
  98        dev->conf.IntType = INT_MEMORY_AND_IO;
  99
 100        dev->io.BasePort2 = 0;
 101        dev->io.NumPorts2 = 0;
 102        dev->io.Attributes2 = 0;
 103
 104        win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
 105                         WIN_ENABLE | WIN_DATA_WIDTH_16 |
 106                         WIN_USE_WAIT;
 107        win.Base = 0;
 108        win.Size = SSB_CORE_SIZE;
 109        win.AccessSpeed = 250;
 110        res = pcmcia_request_window(&dev, &win, &dev->win);
 111        if (res != 0)
 112                goto err_kfree_ssb;
 113
 114        mem.CardOffset = 0;
 115        mem.Page = 0;
 116        res = pcmcia_map_mem_page(dev->win, &mem);
 117        if (res != 0)
 118                goto err_disable;
 119
 120        dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 121        dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
 122        dev->irq.Handler = NULL; /* The handler is registered later. */
 123        dev->irq.Instance = NULL;
 124        res = pcmcia_request_irq(dev, &dev->irq);
 125        if (res != 0)
 126                goto err_disable;
 127
 128        res = pcmcia_request_configuration(dev, &dev->conf);
 129        if (res != 0)
 130                goto err_disable;
 131
 132        err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
 133        if (err)
 134                goto err_disable;
 135        dev->priv = ssb;
 136
 137        return 0;
 138
 139err_disable:
 140        pcmcia_disable_device(dev);
 141err_kfree_ssb:
 142        kfree(ssb);
 143out_error:
 144        printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
 145               res, err);
 146        return err;
 147}
 148
 149static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
 150{
 151        struct ssb_bus *ssb = dev->priv;
 152
 153        ssb_bus_unregister(ssb);
 154        pcmcia_disable_device(dev);
 155        kfree(ssb);
 156        dev->priv = NULL;
 157}
 158
 159static struct pcmcia_driver b43_pcmcia_driver = {
 160        .owner          = THIS_MODULE,
 161        .drv            = {
 162                                .name = "b43-pcmcia",
 163                        },
 164        .id_table       = b43_pcmcia_tbl,
 165        .probe          = b43_pcmcia_probe,
 166        .remove         = __devexit_p(b43_pcmcia_remove),
 167        .suspend        = b43_pcmcia_suspend,
 168        .resume         = b43_pcmcia_resume,
 169};
 170
 171int b43_pcmcia_init(void)
 172{
 173        return pcmcia_register_driver(&b43_pcmcia_driver);
 174}
 175
 176void b43_pcmcia_exit(void)
 177{
 178        pcmcia_unregister_driver(&b43_pcmcia_driver);
 179}
 180