Merge branch 'late/cleanup' into devel-late
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / net / wireless / atmel_cs.c
CommitLineData
1da177e4
LT
1/*** -*- linux-c -*- **********************************************************
2
3 Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
4
5 Copyright 2000-2001 ATMEL Corporation.
6 Copyright 2003 Simon Kelley.
7
5c877fe5
DT
8 This code was developed from version 2.1.1 of the Atmel drivers,
9 released by Atmel corp. under the GPL in December 2002. It also
10 includes code from the Linux aironet drivers (C) Benjamin Reed,
11 and the Linux PCMCIA package, (C) David Hinds.
1da177e4 12
5c877fe5 13 For all queries about this code, please contact the current author,
1da177e4
LT
14 Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20
21 This software is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with Atmel wireless lan drivers; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
30******************************************************************************/
31
1da177e4
LT
32#ifdef __IN_PCMCIA_PACKAGE__
33#include <pcmcia/k_compat.h>
34#endif
35#include <linux/init.h>
36#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/ptrace.h>
39#include <linux/slab.h>
40#include <linux/string.h>
41#include <linux/netdevice.h>
42#include <linux/moduleparam.h>
43#include <linux/device.h>
44
1da177e4
LT
45#include <pcmcia/cistpl.h>
46#include <pcmcia/cisreg.h>
47#include <pcmcia/ds.h>
48#include <pcmcia/ciscode.h>
49
50#include <asm/io.h>
1da177e4
LT
51#include <linux/wireless.h>
52
53#include "atmel.h"
54
1da177e4
LT
55
56/*====================================================================*/
57
58MODULE_AUTHOR("Simon Kelley");
59MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
60MODULE_LICENSE("GPL");
61MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
62
63/*====================================================================*/
64
15b99ac1 65static int atmel_config(struct pcmcia_device *link);
fba395ee 66static void atmel_release(struct pcmcia_device *link);
1da177e4 67
cc3b4866 68static void atmel_detach(struct pcmcia_device *p_dev);
1da177e4 69
1da177e4 70typedef struct local_info_t {
1da177e4
LT
71 struct net_device *eth_dev;
72} local_info_t;
73
15b99ac1 74static int atmel_probe(struct pcmcia_device *p_dev)
1da177e4 75{
1da177e4 76 local_info_t *local;
f8cfa618 77
2caff147 78 dev_dbg(&p_dev->dev, "atmel_attach()\n");
1da177e4 79
1da177e4 80 /* Allocate space for private device-specific data */
b69a3aa8 81 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
1da177e4
LT
82 if (!local) {
83 printk(KERN_ERR "atmel_cs: no memory for new device\n");
f8cfa618 84 return -ENOMEM;
1da177e4 85 }
fd238232 86 p_dev->priv = local;
f8cfa618 87
15b99ac1 88 return atmel_config(p_dev);
1da177e4
LT
89} /* atmel_attach */
90
fba395ee 91static void atmel_detach(struct pcmcia_device *link)
1da177e4 92{
2caff147 93 dev_dbg(&link->dev, "atmel_detach\n");
1da177e4 94
e2d40963 95 atmel_release(link);
b4635811 96
b4558ea9 97 kfree(link->priv);
1da177e4
LT
98}
99
1da177e4 100/* Call-back function to interrogate PCMCIA-specific information
25985edc 101 about the current existence of the card */
1da177e4 102static int card_present(void *arg)
9940ec36 103{
fba395ee 104 struct pcmcia_device *link = (struct pcmcia_device *)arg;
9940ec36
DB
105
106 if (pcmcia_dev_present(link))
1da177e4 107 return 1;
9940ec36 108
1da177e4
LT
109 return 0;
110}
111
00990e7c 112static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
b54bf94b 113{
00990e7c
DB
114 if (p_dev->config_index == 0)
115 return -EINVAL;
b54bf94b 116
90abdc3b 117 return pcmcia_request_io(p_dev);
b54bf94b
DB
118}
119
15b99ac1 120static int atmel_config(struct pcmcia_device *link)
1da177e4 121{
1da177e4 122 local_info_t *dev;
2caff147 123 int ret;
25f8f54f 124 const struct pcmcia_device_id *did;
b16a228d 125
1da177e4 126 dev = link->priv;
dd2e5a15 127 did = dev_get_drvdata(&link->dev);
1da177e4 128
2caff147 129 dev_dbg(&link->dev, "atmel_config\n");
5c877fe5 130
440eed43 131 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
00990e7c 132 CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
440eed43 133
8e2fc39d 134 if (pcmcia_loop_config(link, atmel_config_check, NULL))
b54bf94b 135 goto failed;
5c877fe5 136
eb14120f
DB
137 if (!link->irq) {
138 dev_err(&link->dev, "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
139 goto failed;
2caff147 140 }
5c877fe5 141
1ac71e5a 142 ret = pcmcia_enable_device(link);
2caff147
DB
143 if (ret)
144 goto failed;
5c877fe5 145
5c877fe5 146 ((local_info_t*)link->priv)->eth_dev =
eb14120f 147 init_atmel_card(link->irq,
9a017a91 148 link->resource[0]->start,
b16a228d 149 did ? did->driver_info : ATMEL_FW_TYPE_NONE,
dd2e5a15 150 &link->dev,
5c877fe5 151 card_present,
1da177e4 152 link);
5c877fe5 153 if (!((local_info_t*)link->priv)->eth_dev)
2caff147 154 goto failed;
5c877fe5
DT
155
156
15b99ac1 157 return 0;
e2d40963 158
b54bf94b 159 failed:
1da177e4 160 atmel_release(link);
15b99ac1 161 return -ENODEV;
1da177e4
LT
162}
163
fba395ee 164static void atmel_release(struct pcmcia_device *link)
1da177e4
LT
165{
166 struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
5f2a71fc 167
2caff147 168 dev_dbg(&link->dev, "atmel_release\n");
5f2a71fc
DB
169
170 if (dev)
b16a228d 171 stop_atmel_card(dev);
5f2a71fc
DB
172 ((local_info_t*)link->priv)->eth_dev = NULL;
173
fba395ee 174 pcmcia_disable_device(link);
1da177e4
LT
175}
176
fba395ee 177static int atmel_suspend(struct pcmcia_device *link)
98e4c28b 178{
98e4c28b
DB
179 local_info_t *local = link->priv;
180
e2d40963 181 netif_device_detach(local->eth_dev);
98e4c28b
DB
182
183 return 0;
184}
185
fba395ee 186static int atmel_resume(struct pcmcia_device *link)
98e4c28b 187{
98e4c28b
DB
188 local_info_t *local = link->priv;
189
e2d40963
DB
190 atmel_open(local->eth_dev);
191 netif_device_attach(local->eth_dev);
98e4c28b
DB
192
193 return 0;
194}
195
1da177e4 196/*====================================================================*/
b16a228d
SK
197/* We use the driver_info field to store the correct firmware type for a card. */
198
199#define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
200 .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
201 PCMCIA_DEV_ID_MATCH_CARD_ID, \
202 .manf_id = (manf), \
203 .card_id = (card), \
204 .driver_info = (kernel_ulong_t)(info), }
205
206#define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
207 .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
208 PCMCIA_DEV_ID_MATCH_PROD_ID2, \
209 .prod_id = { (v1), (v2), NULL, NULL }, \
210 .prod_id_hash = { (vh1), (vh2), 0, 0 }, \
211 .driver_info = (kernel_ulong_t)(info), }
212
25f8f54f 213static const struct pcmcia_device_id atmel_ids[] = {
b16a228d
SK
214 PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
215 PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
216 PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
217 PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
218 PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
219 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
220 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
221 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
222 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
223 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
224 PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
225 PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
226 PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
227 PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
228 PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
229 PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
230 PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
231 PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
232 PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
233 PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
234 PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
4a17a119
DB
235 PCMCIA_DEVICE_NULL
236};
b16a228d 237
4a17a119
DB
238MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
239
1da177e4 240static struct pcmcia_driver atmel_driver = {
1e212f36 241 .owner = THIS_MODULE,
2e9b981a 242 .name = "atmel_cs",
15b99ac1 243 .probe = atmel_probe,
cc3b4866 244 .remove = atmel_detach,
4a17a119 245 .id_table = atmel_ids,
98e4c28b
DB
246 .suspend = atmel_suspend,
247 .resume = atmel_resume,
1da177e4
LT
248};
249
06b3a1d1 250static int __init atmel_cs_init(void)
1da177e4
LT
251{
252 return pcmcia_register_driver(&atmel_driver);
253}
254
06b3a1d1 255static void __exit atmel_cs_cleanup(void)
1da177e4
LT
256{
257 pcmcia_unregister_driver(&atmel_driver);
1da177e4
LT
258}
259
260/*
261 This program is free software; you can redistribute it and/or
262 modify it under the terms of the GNU General Public License
263 as published by the Free Software Foundation; either version 2
264 of the License, or (at your option) any later version.
265
266 This program is distributed in the hope that it will be useful,
267 but WITHOUT ANY WARRANTY; without even the implied warranty of
268 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
269 GNU General Public License for more details.
270
271 In addition:
272
273 Redistribution and use in source and binary forms, with or without
274 modification, are permitted provided that the following conditions
275 are met:
276
277 1. Redistributions of source code must retain the above copyright
278 notice, this list of conditions and the following disclaimer.
279 2. Redistributions in binary form must reproduce the above copyright
280 notice, this list of conditions and the following disclaimer in the
281 documentation and/or other materials provided with the distribution.
282 3. The name of the author may not be used to endorse or promote
283 products derived from this software without specific prior written
284 permission.
285
286 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
287 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
288 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
289 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
290 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
291 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
292 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
293 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
294 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
295 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5c877fe5 296 POSSIBILITY OF SUCH DAMAGE.
1da177e4
LT
297*/
298
299module_init(atmel_cs_init);
300module_exit(atmel_cs_cleanup);