OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [wireless/] [airport.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* airport.c
2
 *
3
 * A driver for "Hermes" chipset based Apple Airport wireless
4
 * card.
5
 *
6
 * Copyright notice & release notes in file orinoco.c
7
 *
8
 * Note specific to airport stub:
9
 *
10
 *  0.05 : first version of the new split driver
11
 *  0.06 : fix possible hang on powerup, add sleep support
12
 */
13
 
14
#define DRIVER_NAME "airport"
15
#define PFX DRIVER_NAME ": "
16
 
17
#include <linux/module.h>
18
#include <linux/kernel.h>
19
#include <linux/init.h>
20
#include <linux/delay.h>
21
#include <asm/pmac_feature.h>
22
 
23
#include "orinoco.h"
24
 
25
#define AIRPORT_IO_LEN  (0x1000)        /* one page */
26
 
27
struct airport {
28
        struct macio_dev *mdev;
29
        void __iomem *vaddr;
30
        int irq_requested;
31
        int ndev_registered;
32
};
33
 
34
static int
35
airport_suspend(struct macio_dev *mdev, pm_message_t state)
36
{
37
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
38
        struct orinoco_private *priv = netdev_priv(dev);
39
        unsigned long flags;
40
        int err;
41
 
42
        printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
43
 
44
        err = orinoco_lock(priv, &flags);
45
        if (err) {
46
                printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
47
                       dev->name);
48
                return 0;
49
        }
50
 
51
        err = __orinoco_down(dev);
52
        if (err)
53
                printk(KERN_WARNING "%s: PBOOK_SLEEP_NOW: Error %d downing interface\n",
54
                       dev->name, err);
55
 
56
        netif_device_detach(dev);
57
 
58
        priv->hw_unavailable++;
59
 
60
        orinoco_unlock(priv, &flags);
61
 
62
        disable_irq(dev->irq);
63
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
64
 
65
        return 0;
66
}
67
 
68
static int
69
airport_resume(struct macio_dev *mdev)
70
{
71
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
72
        struct orinoco_private *priv = netdev_priv(dev);
73
        unsigned long flags;
74
        int err;
75
 
76
        printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
77
 
78
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
79
        msleep(200);
80
 
81
        enable_irq(dev->irq);
82
 
83
        err = orinoco_reinit_firmware(dev);
84
        if (err) {
85
                printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
86
                       dev->name, err);
87
                return 0;
88
        }
89
 
90
        spin_lock_irqsave(&priv->lock, flags);
91
 
92
        netif_device_attach(dev);
93
 
94
        priv->hw_unavailable--;
95
 
96
        if (priv->open && (! priv->hw_unavailable)) {
97
                err = __orinoco_up(dev);
98
                if (err)
99
                        printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n",
100
                               dev->name, err);
101
        }
102
 
103
 
104
        spin_unlock_irqrestore(&priv->lock, flags);
105
 
106
        return 0;
107
}
108
 
109
static int
110
airport_detach(struct macio_dev *mdev)
111
{
112
        struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
113
        struct orinoco_private *priv = netdev_priv(dev);
114
        struct airport *card = priv->card;
115
 
116
        if (card->ndev_registered)
117
                unregister_netdev(dev);
118
        card->ndev_registered = 0;
119
 
120
        if (card->irq_requested)
121
                free_irq(dev->irq, dev);
122
        card->irq_requested = 0;
123
 
124
        if (card->vaddr)
125
                iounmap(card->vaddr);
126
        card->vaddr = NULL;
127
 
128
        macio_release_resource(mdev, 0);
129
 
130
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
131
        ssleep(1);
132
 
133
        macio_set_drvdata(mdev, NULL);
134
        free_orinocodev(dev);
135
 
136
        return 0;
137
}
138
 
139
static int airport_hard_reset(struct orinoco_private *priv)
140
{
141
        /* It would be nice to power cycle the Airport for a real hard
142
         * reset, but for some reason although it appears to
143
         * re-initialize properly, it falls in a screaming heap
144
         * shortly afterwards. */
145
#if 0
146
        struct net_device *dev = priv->ndev;
147
        struct airport *card = priv->card;
148
 
149
        /* Vitally important.  If we don't do this it seems we get an
150
         * interrupt somewhere during the power cycle, since
151
         * hw_unavailable is already set it doesn't get ACKed, we get
152
         * into an interrupt loop and the PMU decides to turn us
153
         * off. */
154
        disable_irq(dev->irq);
155
 
156
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
157
        ssleep(1);
158
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
159
        ssleep(1);
160
 
161
        enable_irq(dev->irq);
162
        ssleep(1);
163
#endif
164
 
165
        return 0;
166
}
167
 
168
static int
169
airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
170
{
171
        struct orinoco_private *priv;
172
        struct net_device *dev;
173
        struct airport *card;
174
        unsigned long phys_addr;
175
        hermes_t *hw;
176
 
177
        if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
178
                printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
179
                return -ENODEV;
180
        }
181
 
182
        /* Allocate space for private device-specific data */
183
        dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
184
        if (! dev) {
185
                printk(KERN_ERR PFX "Cannot allocate network device\n");
186
                return -ENODEV;
187
        }
188
        priv = netdev_priv(dev);
189
        card = priv->card;
190
 
191
        hw = &priv->hw;
192
        card->mdev = mdev;
193
 
194
        if (macio_request_resource(mdev, 0, "airport")) {
195
                printk(KERN_ERR PFX "can't request IO resource !\n");
196
                free_orinocodev(dev);
197
                return -EBUSY;
198
        }
199
 
200
        SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
201
 
202
        macio_set_drvdata(mdev, dev);
203
 
204
        /* Setup interrupts & base address */
205
        dev->irq = macio_irq(mdev, 0);
206
        phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
207
        printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
208
        dev->base_addr = phys_addr;
209
        card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
210
        if (!card->vaddr) {
211
                printk(KERN_ERR PFX "ioremap() failed\n");
212
                goto failed;
213
        }
214
 
215
        hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
216
 
217
        /* Power up card */
218
        pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
219
        ssleep(1);
220
 
221
        /* Reset it before we get the interrupt */
222
        hermes_init(hw);
223
 
224
        if (request_irq(dev->irq, orinoco_interrupt, 0, dev->name, dev)) {
225
                printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
226
                goto failed;
227
        }
228
        card->irq_requested = 1;
229
 
230
        /* Tell the stack we exist */
231
        if (register_netdev(dev) != 0) {
232
                printk(KERN_ERR PFX "register_netdev() failed\n");
233
                goto failed;
234
        }
235
        printk(KERN_DEBUG PFX "Card registered for interface %s\n", dev->name);
236
        card->ndev_registered = 1;
237
        return 0;
238
 failed:
239
        airport_detach(mdev);
240
        return -ENODEV;
241
}                               /* airport_attach */
242
 
243
 
244
static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
245
        " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
246
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
247
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
248
MODULE_LICENSE("Dual MPL/GPL");
249
 
250
static struct of_device_id airport_match[] =
251
{
252
        {
253
        .name           = "radio",
254
        },
255
        {},
256
};
257
 
258
MODULE_DEVICE_TABLE (of, airport_match);
259
 
260
static struct macio_driver airport_driver =
261
{
262
        .name           = DRIVER_NAME,
263
        .match_table    = airport_match,
264
        .probe          = airport_attach,
265
        .remove         = airport_detach,
266
        .suspend        = airport_suspend,
267
        .resume         = airport_resume,
268
};
269
 
270
static int __init
271
init_airport(void)
272
{
273
        printk(KERN_DEBUG "%s\n", version);
274
 
275
        return macio_register_driver(&airport_driver);
276
}
277
 
278
static void __exit
279
exit_airport(void)
280
{
281
        return macio_unregister_driver(&airport_driver);
282
}
283
 
284
module_init(init_airport);
285
module_exit(exit_airport);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.