phy: Add suspend/resume support to SMSC PHYs
[deliverable/linux.git] / drivers / net / wireless / p54 / p54usb.c
CommitLineData
eff1a59c
MW
1
2/*
3 * Linux device driver for USB based Prism54
4 *
5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
6 *
7 * Based on the islsm (softmac prism54) driver, which is:
8 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/usb.h>
17#include <linux/pci.h>
18#include <linux/firmware.h>
19#include <linux/etherdevice.h>
20#include <linux/delay.h>
21#include <linux/crc32.h>
22#include <net/mac80211.h>
23
24#include "p54.h"
25#include "p54usb.h"
26
27MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
28MODULE_DESCRIPTION("Prism54 USB wireless driver");
29MODULE_LICENSE("GPL");
30MODULE_ALIAS("prism54usb");
9a8675d7
CL
31MODULE_FIRMWARE("isl3886usb");
32MODULE_FIRMWARE("isl3887usb");
eff1a59c
MW
33
34static struct usb_device_id p54u_table[] __devinitdata = {
35 /* Version 1 devices (pci chip + net2280) */
36 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
37 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
38 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
39 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
1a17582e 40 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
eff1a59c
MW
41 {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
42 {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
43 {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
ec366eba 44 {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
eff1a59c
MW
45 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
46 {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
47 {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
48 {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
49 {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
50 {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
51 {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
52 {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
53
54 /* Version 2 devices (3887) */
4546002c 55 {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */
eff1a59c
MW
56 {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
57 {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
58 {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
878e6a43 59 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
eff1a59c
MW
60 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
61 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
62 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
63 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
64 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
65 {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
66 {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
67 {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
68 {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
69 {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
43557e15 70 {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
ec366eba 71 {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
387e100a 72 {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
c1098103 73 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
eff1a59c
MW
74 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
75 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
76 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
77 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
78 {}
79};
80
81MODULE_DEVICE_TABLE(usb, p54u_table);
82
83static void p54u_rx_cb(struct urb *urb)
84{
85 struct sk_buff *skb = (struct sk_buff *) urb->context;
86 struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
87 struct ieee80211_hw *dev = info->dev;
88 struct p54u_priv *priv = dev->priv;
89
dd397dc9
CL
90 skb_unlink(skb, &priv->rx_queue);
91
eff1a59c 92 if (unlikely(urb->status)) {
dd397dc9 93 dev_kfree_skb_irq(skb);
eff1a59c
MW
94 return;
95 }
96
eff1a59c 97 skb_put(skb, urb->actual_length);
2b80848e
CL
98
99 if (priv->hw_type == P54U_NET2280)
100 skb_pull(skb, priv->common.tx_hdr_len);
101 if (priv->common.fw_interface == FW_LM87) {
102 skb_pull(skb, 4);
103 skb_put(skb, 4);
104 }
eff1a59c
MW
105
106 if (p54_rx(dev, skb)) {
4e416a6f 107 skb = dev_alloc_skb(priv->common.rx_mtu + 32);
eff1a59c 108 if (unlikely(!skb)) {
eff1a59c
MW
109 /* TODO check rx queue length and refill *somewhere* */
110 return;
111 }
112
113 info = (struct p54u_rx_info *) skb->cb;
114 info->urb = urb;
115 info->dev = dev;
116 urb->transfer_buffer = skb_tail_pointer(skb);
117 urb->context = skb;
eff1a59c 118 } else {
2b80848e
CL
119 if (priv->hw_type == P54U_NET2280)
120 skb_push(skb, priv->common.tx_hdr_len);
121 if (priv->common.fw_interface == FW_LM87) {
122 skb_push(skb, 4);
123 skb_put(skb, 4);
124 }
d47c3ceb 125 skb_reset_tail_pointer(skb);
eff1a59c 126 skb_trim(skb, 0);
d47c3ceb
CL
127 if (urb->transfer_buffer != skb_tail_pointer(skb)) {
128 /* this should not happen */
129 WARN_ON(1);
130 urb->transfer_buffer = skb_tail_pointer(skb);
131 }
eff1a59c 132 }
dd397dc9
CL
133 skb_queue_tail(&priv->rx_queue, skb);
134 usb_anchor_urb(urb, &priv->submitted);
135 if (usb_submit_urb(urb, GFP_ATOMIC)) {
136 skb_unlink(skb, &priv->rx_queue);
137 usb_unanchor_urb(urb);
138 dev_kfree_skb_irq(skb);
139 }
eff1a59c
MW
140}
141
0a5ec96a 142static void p54u_tx_cb(struct urb *urb)
b92f30d6
CL
143{
144 struct sk_buff *skb = urb->context;
145 struct ieee80211_hw *dev = (struct ieee80211_hw *)
146 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
147
e2fe154e 148 p54_free_skb(dev, skb);
dd397dc9
CL
149}
150
151static void p54u_tx_dummy_cb(struct urb *urb) { }
152
153static void p54u_free_urbs(struct ieee80211_hw *dev)
154{
155 struct p54u_priv *priv = dev->priv;
156 usb_kill_anchored_urbs(&priv->submitted);
b92f30d6
CL
157}
158
eff1a59c
MW
159static int p54u_init_urbs(struct ieee80211_hw *dev)
160{
161 struct p54u_priv *priv = dev->priv;
dd397dc9 162 struct urb *entry = NULL;
eff1a59c
MW
163 struct sk_buff *skb;
164 struct p54u_rx_info *info;
dd397dc9 165 int ret = 0;
eff1a59c
MW
166
167 while (skb_queue_len(&priv->rx_queue) < 32) {
4e416a6f 168 skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
dd397dc9
CL
169 if (!skb) {
170 ret = -ENOMEM;
171 goto err;
172 }
eff1a59c
MW
173 entry = usb_alloc_urb(0, GFP_KERNEL);
174 if (!entry) {
dd397dc9
CL
175 ret = -ENOMEM;
176 goto err;
eff1a59c 177 }
dd397dc9 178
4e416a6f
CL
179 usb_fill_bulk_urb(entry, priv->udev,
180 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
181 skb_tail_pointer(skb),
182 priv->common.rx_mtu + 32, p54u_rx_cb, skb);
eff1a59c
MW
183 info = (struct p54u_rx_info *) skb->cb;
184 info->urb = entry;
185 info->dev = dev;
186 skb_queue_tail(&priv->rx_queue, skb);
dd397dc9
CL
187
188 usb_anchor_urb(entry, &priv->submitted);
189 ret = usb_submit_urb(entry, GFP_KERNEL);
190 if (ret) {
191 skb_unlink(skb, &priv->rx_queue);
192 usb_unanchor_urb(entry);
193 goto err;
194 }
195 usb_free_urb(entry);
196 entry = NULL;
eff1a59c
MW
197 }
198
199 return 0;
eff1a59c 200
dd397dc9
CL
201 err:
202 usb_free_urb(entry);
203 kfree_skb(skb);
204 p54u_free_urbs(dev);
205 return ret;
eff1a59c
MW
206}
207
0a5ec96a 208static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
eff1a59c
MW
209{
210 struct p54u_priv *priv = dev->priv;
211 struct urb *addr_urb, *data_urb;
dd397dc9 212 int err = 0;
eff1a59c
MW
213
214 addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
215 if (!addr_urb)
216 return;
217
218 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
219 if (!data_urb) {
220 usb_free_urb(addr_urb);
221 return;
222 }
223
224 usb_fill_bulk_urb(addr_urb, priv->udev,
b92f30d6 225 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
27df605e 226 &((struct p54_hdr *)skb->data)->req_id, 4,
dd397dc9 227 p54u_tx_dummy_cb, dev);
eff1a59c 228 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 229 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
230 skb->data, skb->len, FREE_AFTER_TX(skb) ?
231 p54u_tx_cb : p54u_tx_dummy_cb, skb);
eff1a59c 232
dd397dc9
CL
233 usb_anchor_urb(addr_urb, &priv->submitted);
234 err = usb_submit_urb(addr_urb, GFP_ATOMIC);
235 if (err) {
236 usb_unanchor_urb(addr_urb);
237 goto out;
238 }
239
240 usb_anchor_urb(addr_urb, &priv->submitted);
241 err = usb_submit_urb(data_urb, GFP_ATOMIC);
242 if (err)
243 usb_unanchor_urb(data_urb);
244
245 out:
246 usb_free_urb(addr_urb);
247 usb_free_urb(data_urb);
248
249 if (err)
250 p54_free_skb(dev, skb);
eff1a59c
MW
251}
252
c9127659 253static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
2b80848e 254{
1f1c0e33 255 u32 chk = 0;
2b80848e
CL
256
257 length >>= 2;
258 while (length--) {
c9127659 259 chk ^= le32_to_cpu(*data++);
2b80848e
CL
260 chk = (chk >> 5) ^ (chk << 3);
261 }
262
1f1c0e33 263 return cpu_to_le32(chk);
2b80848e
CL
264}
265
0a5ec96a 266static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
2b80848e
CL
267{
268 struct p54u_priv *priv = dev->priv;
269 struct urb *data_urb;
e2fe154e 270 struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
2b80848e
CL
271
272 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
273 if (!data_urb)
274 return;
275
e2fe154e
CL
276 hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
277 hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
2b80848e
CL
278
279 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 280 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
281 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
282 p54u_tx_cb : p54u_tx_dummy_cb, skb);
00627f22 283 data_urb->transfer_flags |= URB_ZERO_PACKET;
2b80848e 284
dd397dc9
CL
285 usb_anchor_urb(data_urb, &priv->submitted);
286 if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
287 usb_unanchor_urb(data_urb);
dd397dc9
CL
288 p54_free_skb(dev, skb);
289 }
290 usb_free_urb(data_urb);
2b80848e
CL
291}
292
0a5ec96a 293static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
eff1a59c
MW
294{
295 struct p54u_priv *priv = dev->priv;
296 struct urb *int_urb, *data_urb;
e2fe154e 297 struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
eff1a59c 298 struct net2280_reg_write *reg;
dd397dc9 299 int err = 0;
eff1a59c
MW
300
301 reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
302 if (!reg)
303 return;
304
305 int_urb = usb_alloc_urb(0, GFP_ATOMIC);
306 if (!int_urb) {
307 kfree(reg);
308 return;
309 }
310
311 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
312 if (!data_urb) {
313 kfree(reg);
314 usb_free_urb(int_urb);
315 return;
316 }
317
318 reg->port = cpu_to_le16(NET2280_DEV_U32);
319 reg->addr = cpu_to_le32(P54U_DEV_BASE);
320 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
321
eff1a59c 322 memset(hdr, 0, sizeof(*hdr));
e2fe154e
CL
323 hdr->len = cpu_to_le16(skb->len);
324 hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;
eff1a59c
MW
325
326 usb_fill_bulk_urb(int_urb, priv->udev,
327 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
dd397dc9
CL
328 p54u_tx_dummy_cb, dev);
329
330 /*
331 * This flag triggers a code path in the USB subsystem that will
332 * free what's inside the transfer_buffer after the callback routine
333 * has completed.
334 */
335 int_urb->transfer_flags |= URB_FREE_BUFFER;
eff1a59c
MW
336
337 usb_fill_bulk_urb(data_urb, priv->udev,
b92f30d6 338 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
e2fe154e
CL
339 hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
340 p54u_tx_cb : p54u_tx_dummy_cb, skb);
dd397dc9
CL
341
342 usb_anchor_urb(int_urb, &priv->submitted);
343 err = usb_submit_urb(int_urb, GFP_ATOMIC);
344 if (err) {
345 usb_unanchor_urb(int_urb);
346 goto out;
347 }
348
349 usb_anchor_urb(data_urb, &priv->submitted);
350 err = usb_submit_urb(data_urb, GFP_ATOMIC);
351 if (err) {
352 usb_unanchor_urb(data_urb);
353 goto out;
354 }
355 out:
356 usb_free_urb(int_urb);
357 usb_free_urb(data_urb);
358
359 if (err) {
360 skb_pull(skb, sizeof(*hdr));
361 p54_free_skb(dev, skb);
362 }
eff1a59c
MW
363}
364
365static int p54u_write(struct p54u_priv *priv,
366 struct net2280_reg_write *buf,
367 enum net2280_op_type type,
368 __le32 addr, __le32 val)
369{
370 unsigned int ep;
371 int alen;
372
373 if (type & 0x0800)
374 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
375 else
376 ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
377
378 buf->port = cpu_to_le16(type);
379 buf->addr = addr;
380 buf->val = val;
381
382 return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
383}
384
385static int p54u_read(struct p54u_priv *priv, void *buf,
386 enum net2280_op_type type,
387 __le32 addr, __le32 *val)
388{
389 struct net2280_reg_read *read = buf;
390 __le32 *reg = buf;
391 unsigned int ep;
392 int alen, err;
393
394 if (type & 0x0800)
395 ep = P54U_PIPE_DEV;
396 else
397 ep = P54U_PIPE_BRG;
398
399 read->port = cpu_to_le16(type);
400 read->addr = addr;
401
402 err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
403 read, sizeof(*read), &alen, 1000);
404 if (err)
405 return err;
406
407 err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
408 reg, sizeof(*reg), &alen, 1000);
409 if (err)
410 return err;
411
412 *val = *reg;
413 return 0;
414}
415
416static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
417 void *data, size_t len)
418{
419 int alen;
420 return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
421 data, len, &alen, 2000);
422}
423
eff1a59c
MW
424static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
425{
426 static char start_string[] = "~~~~<\r";
427 struct p54u_priv *priv = dev->priv;
428 const struct firmware *fw_entry = NULL;
429 int err, alen;
430 u8 carry = 0;
8b72eb43
DW
431 u8 *buf, *tmp;
432 const u8 *data;
eff1a59c
MW
433 unsigned int left, remains, block_size;
434 struct x2_header *hdr;
435 unsigned long timeout;
436
437 tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
438 if (!buf) {
02e37ba1
CL
439 dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
440 "upload buffer!\n");
eff1a59c
MW
441 err = -ENOMEM;
442 goto err_bufalloc;
443 }
444
445 memcpy(buf, start_string, 4);
446 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
447 if (err) {
02e37ba1 448 dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
eff1a59c
MW
449 goto err_reset;
450 }
451
9a8675d7 452 err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
eff1a59c 453 if (err) {
02e37ba1
CL
454 dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
455 "(isl3887usb)\n");
9a8675d7
CL
456 err = request_firmware(&fw_entry, "isl3887usb_bare",
457 &priv->udev->dev);
458 if (err)
459 goto err_req_fw_failed;
eff1a59c
MW
460 }
461
4e416a6f
CL
462 err = p54_parse_firmware(dev, fw_entry);
463 if (err)
464 goto err_upload_failed;
eff1a59c
MW
465
466 left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
467 strcpy(buf, start_string);
468 left -= strlen(start_string);
469 tmp += strlen(start_string);
470
471 data = fw_entry->data;
472 remains = fw_entry->size;
473
474 hdr = (struct x2_header *)(buf + strlen(start_string));
475 memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
476 hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
477 hdr->fw_length = cpu_to_le32(fw_entry->size);
478 hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
479 sizeof(u32)*2));
480 left -= sizeof(*hdr);
481 tmp += sizeof(*hdr);
482
483 while (remains) {
484 while (left--) {
485 if (carry) {
486 *tmp++ = carry;
487 carry = 0;
488 remains--;
489 continue;
490 }
491 switch (*data) {
492 case '~':
493 *tmp++ = '}';
494 carry = '^';
495 break;
496 case '}':
497 *tmp++ = '}';
498 carry = ']';
499 break;
500 default:
501 *tmp++ = *data;
502 remains--;
503 break;
504 }
505 data++;
506 }
507
508 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
509 if (err) {
02e37ba1
CL
510 dev_err(&priv->udev->dev, "(p54usb) firmware "
511 "upload failed!\n");
eff1a59c
MW
512 goto err_upload_failed;
513 }
514
515 tmp = buf;
516 left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
517 }
518
519 *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
520 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
521 if (err) {
02e37ba1 522 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c
MW
523 goto err_upload_failed;
524 }
eff1a59c
MW
525 timeout = jiffies + msecs_to_jiffies(1000);
526 while (!(err = usb_bulk_msg(priv->udev,
527 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
528 if (alen > 2 && !memcmp(buf, "OK", 2))
529 break;
530
531 if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
eff1a59c
MW
532 err = -EINVAL;
533 break;
534 }
535
536 if (time_after(jiffies, timeout)) {
02e37ba1
CL
537 dev_err(&priv->udev->dev, "(p54usb) firmware boot "
538 "timed out!\n");
eff1a59c
MW
539 err = -ETIMEDOUT;
540 break;
541 }
542 }
02e37ba1
CL
543 if (err) {
544 dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
eff1a59c 545 goto err_upload_failed;
02e37ba1 546 }
eff1a59c
MW
547
548 buf[0] = 'g';
549 buf[1] = '\r';
550 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
551 if (err) {
02e37ba1 552 dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");
eff1a59c
MW
553 goto err_upload_failed;
554 }
555
556 timeout = jiffies + msecs_to_jiffies(1000);
557 while (!(err = usb_bulk_msg(priv->udev,
558 usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
559 if (alen > 0 && buf[0] == 'g')
560 break;
561
562 if (time_after(jiffies, timeout)) {
563 err = -ETIMEDOUT;
564 break;
565 }
566 }
567 if (err)
568 goto err_upload_failed;
569
570 err_upload_failed:
571 release_firmware(fw_entry);
572 err_req_fw_failed:
573 err_reset:
574 kfree(buf);
575 err_bufalloc:
576 return err;
577}
578
579static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
580{
581 struct p54u_priv *priv = dev->priv;
582 const struct firmware *fw_entry = NULL;
583 const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
584 int err, alen;
585 void *buf;
586 __le32 reg;
587 unsigned int remains, offset;
8b72eb43 588 const u8 *data;
eff1a59c
MW
589
590 buf = kmalloc(512, GFP_KERNEL);
591 if (!buf) {
02e37ba1
CL
592 dev_err(&priv->udev->dev, "(p54usb) firmware buffer "
593 "alloc failed!\n");
eff1a59c
MW
594 return -ENOMEM;
595 }
596
9a8675d7 597 err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
eff1a59c 598 if (err) {
02e37ba1
CL
599 dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
600 "(isl3886usb)\n");
9a8675d7
CL
601 err = request_firmware(&fw_entry, "isl3890usb",
602 &priv->udev->dev);
603 if (err) {
604 kfree(buf);
605 return err;
606 }
eff1a59c
MW
607 }
608
4e416a6f
CL
609 err = p54_parse_firmware(dev, fw_entry);
610 if (err) {
611 kfree(buf);
612 release_firmware(fw_entry);
613 return err;
614 }
eff1a59c
MW
615
616#define P54U_WRITE(type, addr, data) \
617 do {\
618 err = p54u_write(priv, buf, type,\
619 cpu_to_le32((u32)(unsigned long)addr), data);\
620 if (err) \
621 goto fail;\
622 } while (0)
623
624#define P54U_READ(type, addr) \
625 do {\
626 err = p54u_read(priv, buf, type,\
627 cpu_to_le32((u32)(unsigned long)addr), &reg);\
628 if (err)\
629 goto fail;\
630 } while (0)
631
632 /* power down net2280 bridge */
633 P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
634 reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
635 reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
636 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
637
638 mdelay(100);
639
640 /* power up bridge */
641 reg |= cpu_to_le32(P54U_BRG_POWER_UP);
642 reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
643 P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
644
645 mdelay(100);
646
647 P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
648 cpu_to_le32(NET2280_CLK_30Mhz |
649 NET2280_PCI_ENABLE |
650 NET2280_PCI_SOFT_RESET));
651
652 mdelay(20);
653
654 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
655 cpu_to_le32(PCI_COMMAND_MEMORY |
656 PCI_COMMAND_MASTER));
657
658 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
659 cpu_to_le32(NET2280_BASE));
660
661 P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
662 reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
663 P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
664
665 // TODO: we really need this?
666 P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
667
668 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
669 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
670 P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
671 cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
672
673 P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
674 cpu_to_le32(NET2280_BASE2));
675
676 /* finally done setting up the bridge */
677
678 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
679 cpu_to_le32(PCI_COMMAND_MEMORY |
680 PCI_COMMAND_MASTER));
681
682 P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
683 P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
684 cpu_to_le32(P54U_DEV_BASE));
685
686 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
687 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
688 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
689
690 /* do romboot */
691 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
692
693 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
694 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
695 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
696 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
697 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
698
699 mdelay(20);
700
701 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
702 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
703
704 mdelay(20);
705
706 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
707 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
708
709 mdelay(100);
710
711 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
712 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
713
714 /* finally, we can upload firmware now! */
715 remains = fw_entry->size;
716 data = fw_entry->data;
717 offset = ISL38XX_DEV_FIRMWARE_ADDR;
718
719 while (remains) {
720 unsigned int block_len = min(remains, (unsigned int)512);
721 memcpy(buf, data, block_len);
722
723 err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
724 if (err) {
02e37ba1
CL
725 dev_err(&priv->udev->dev, "(p54usb) firmware block "
726 "upload failed\n");
eff1a59c
MW
727 goto fail;
728 }
729
730 P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
731 cpu_to_le32(0xc0000f00));
732
733 P54U_WRITE(NET2280_DEV_U32,
734 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
735 P54U_WRITE(NET2280_DEV_U32,
736 0x0020 | (unsigned long)&devreg->direct_mem_win,
737 cpu_to_le32(1));
738
739 P54U_WRITE(NET2280_DEV_U32,
740 0x0024 | (unsigned long)&devreg->direct_mem_win,
741 cpu_to_le32(block_len));
742 P54U_WRITE(NET2280_DEV_U32,
743 0x0028 | (unsigned long)&devreg->direct_mem_win,
744 cpu_to_le32(offset));
745
746 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
747 cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
748 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
749 cpu_to_le32(block_len >> 2));
750 P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
751 cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
752
753 mdelay(10);
754
755 P54U_READ(NET2280_DEV_U32,
756 0x002C | (unsigned long)&devreg->direct_mem_win);
757 if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
758 !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
02e37ba1
CL
759 dev_err(&priv->udev->dev, "(p54usb) firmware DMA "
760 "transfer failed\n");
eff1a59c
MW
761 goto fail;
762 }
763
764 P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
765 cpu_to_le32(NET2280_FIFO_FLUSH));
766
767 remains -= block_len;
768 data += block_len;
769 offset += block_len;
770 }
771
772 /* do ramboot */
773 P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
774 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
775 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
776 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
777 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
778
779 mdelay(20);
780
781 reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
782 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
783
784 reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
785 P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
786
787 mdelay(100);
788
789 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
790 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
791
792 /* start up the firmware */
793 P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
794 cpu_to_le32(ISL38XX_INT_IDENT_INIT));
795
796 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
797 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
798
799 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
800 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
801 NET2280_USB_INTERRUPT_ENABLE));
802
803 P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
804 cpu_to_le32(ISL38XX_DEV_INT_RESET));
805
806 err = usb_interrupt_msg(priv->udev,
807 usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
808 buf, sizeof(__le32), &alen, 1000);
809 if (err || alen != sizeof(__le32))
810 goto fail;
811
812 P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
813 P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
814
815 if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
816 err = -EINVAL;
817
818 P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
819 P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
820 cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
821
822#undef P54U_WRITE
823#undef P54U_READ
824
825 fail:
826 release_firmware(fw_entry);
827 kfree(buf);
828 return err;
829}
830
831static int p54u_open(struct ieee80211_hw *dev)
832{
833 struct p54u_priv *priv = dev->priv;
834 int err;
835
836 err = p54u_init_urbs(dev);
837 if (err) {
838 return err;
839 }
840
841 priv->common.open = p54u_init_urbs;
842
843 return 0;
844}
845
846static void p54u_stop(struct ieee80211_hw *dev)
847{
848 /* TODO: figure out how to reliably stop the 3887 and net2280 so
849 the hardware is still usable next time we want to start it.
850 until then, we just stop listening to the hardware.. */
851 p54u_free_urbs(dev);
852 return;
853}
854
855static int __devinit p54u_probe(struct usb_interface *intf,
856 const struct usb_device_id *id)
857{
858 struct usb_device *udev = interface_to_usbdev(intf);
859 struct ieee80211_hw *dev;
860 struct p54u_priv *priv;
861 int err;
862 unsigned int i, recognized_pipes;
eff1a59c
MW
863
864 dev = p54_init_common(sizeof(*priv));
02e37ba1 865
eff1a59c 866 if (!dev) {
02e37ba1 867 dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");
eff1a59c
MW
868 return -ENOMEM;
869 }
870
871 priv = dev->priv;
872
873 SET_IEEE80211_DEV(dev, &intf->dev);
874 usb_set_intfdata(intf, dev);
875 priv->udev = udev;
876
877 usb_get_dev(udev);
878
879 /* really lazy and simple way of figuring out if we're a 3887 */
880 /* TODO: should just stick the identification in the device table */
881 i = intf->altsetting->desc.bNumEndpoints;
882 recognized_pipes = 0;
883 while (i--) {
884 switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
885 case P54U_PIPE_DATA:
886 case P54U_PIPE_MGMT:
887 case P54U_PIPE_BRG:
888 case P54U_PIPE_DEV:
889 case P54U_PIPE_DATA | USB_DIR_IN:
890 case P54U_PIPE_MGMT | USB_DIR_IN:
891 case P54U_PIPE_BRG | USB_DIR_IN:
892 case P54U_PIPE_DEV | USB_DIR_IN:
893 case P54U_PIPE_INT | USB_DIR_IN:
894 recognized_pipes++;
895 }
896 }
897 priv->common.open = p54u_open;
2b80848e 898 priv->common.stop = p54u_stop;
eff1a59c
MW
899 if (recognized_pipes < P54U_PIPE_NUMBER) {
900 priv->hw_type = P54U_3887;
2b80848e
CL
901 err = p54u_upload_firmware_3887(dev);
902 if (priv->common.fw_interface == FW_LM87) {
903 dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
904 priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
905 priv->common.tx = p54u_tx_lm87;
906 } else
907 priv->common.tx = p54u_tx_3887;
eff1a59c 908 } else {
2b80848e 909 priv->hw_type = P54U_NET2280;
eff1a59c
MW
910 dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
911 priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
912 priv->common.tx = p54u_tx_net2280;
eff1a59c 913 err = p54u_upload_firmware_net2280(dev);
2b80848e 914 }
eff1a59c
MW
915 if (err)
916 goto err_free_dev;
917
7cb77072 918 skb_queue_head_init(&priv->rx_queue);
dd397dc9 919 init_usb_anchor(&priv->submitted);
7cb77072
CL
920
921 p54u_open(dev);
922 err = p54_read_eeprom(dev);
923 p54u_stop(dev);
eff1a59c
MW
924 if (err)
925 goto err_free_dev;
926
eff1a59c
MW
927 err = ieee80211_register_hw(dev);
928 if (err) {
02e37ba1 929 dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n");
eff1a59c
MW
930 goto err_free_dev;
931 }
932
eff1a59c
MW
933 return 0;
934
935 err_free_dev:
936 ieee80211_free_hw(dev);
937 usb_set_intfdata(intf, NULL);
938 usb_put_dev(udev);
939 return err;
940}
941
942static void __devexit p54u_disconnect(struct usb_interface *intf)
943{
944 struct ieee80211_hw *dev = usb_get_intfdata(intf);
945 struct p54u_priv *priv;
946
947 if (!dev)
948 return;
949
950 ieee80211_unregister_hw(dev);
951
952 priv = dev->priv;
953 usb_put_dev(interface_to_usbdev(intf));
954 p54_free_common(dev);
955 ieee80211_free_hw(dev);
956}
957
958static struct usb_driver p54u_driver = {
32ddf071 959 .name = "p54usb",
eff1a59c
MW
960 .id_table = p54u_table,
961 .probe = p54u_probe,
962 .disconnect = p54u_disconnect,
963};
964
965static int __init p54u_init(void)
966{
967 return usb_register(&p54u_driver);
968}
969
970static void __exit p54u_exit(void)
971{
972 usb_deregister(&p54u_driver);
973}
974
975module_init(p54u_init);
976module_exit(p54u_exit);
This page took 0.37513 seconds and 5 git commands to generate.