Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / ks7010 / ks7010_sdio.c
CommitLineData
13a9930d
WS
1/*
2 * Driver for KeyStream, KS7010 based SDIO cards.
3 *
13a9930d
WS
4 * Copyright (C) 2006-2008 KeyStream Corp.
5 * Copyright (C) 2009 Renesas Technology Corp.
c5d9a030 6 * Copyright (C) 2016 Sang Engineering, Wolfram Sang
13a9930d
WS
7 *
8 * This program is free software; you can redistribute it and/or modify
c5d9a030
WS
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13a9930d
WS
11 */
12
1c013a5c 13#include <linux/firmware.h>
13a9930d
WS
14#include <linux/mmc/card.h>
15#include <linux/mmc/sdio_func.h>
1c013a5c
WS
16#include <linux/workqueue.h>
17#include <asm/atomic.h>
13a9930d
WS
18
19#include "ks_wlan.h"
20#include "ks_wlan_ioctl.h"
13a9930d 21#include "ks_hostif.h"
13a9930d
WS
22#include "ks7010_sdio.h"
23
24#define KS7010_FUNC_NUM 1
25#define KS7010_IO_BLOCK_SIZE 512
26#define KS7010_MAX_CLOCK 25000000
27
f9b5bd05 28static const struct sdio_device_id ks7010_sdio_ids[] = {
cdf6ecc5
WS
29 {SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_A, SDIO_DEVICE_ID_KS_7010)},
30 {SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_B, SDIO_DEVICE_ID_KS_7010)},
13a9930d
WS
31 { /* all zero */ }
32};
f9b5bd05 33MODULE_DEVICE_TABLE(sdio, ks7010_sdio_ids);
13a9930d 34
13a9930d
WS
35/* macro */
36
37#define inc_txqhead(priv) \
38 ( priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE )
39#define inc_txqtail(priv) \
40 ( priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE )
41#define cnt_txqbody(priv) \
42 (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE )
43
44#define inc_rxqhead(priv) \
45 ( priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE )
46#define inc_rxqtail(priv) \
47 ( priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE )
48#define cnt_rxqbody(priv) \
49 (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE )
50
4c0d46d2
WS
51static int ks7010_sdio_read(struct ks_wlan_private *priv, unsigned int address,
52 unsigned char *buffer, int length)
53{
54 struct ks_sdio_card *card;
55 int rc;
56
57 card = priv->ks_wlan_hw.sdio_card;
58
59 if (length == 1) /* CMD52 */
60 *buffer = sdio_readb(card->func, address, &rc);
61 else /* CMD53 multi-block transfer */
62 rc = sdio_memcpy_fromio(card->func, buffer, address, length);
63
64 if (rc != 0)
65 DPRINTK(1, "sdio error=%d size=%d\n", rc, length);
66
67 return rc;
68}
69
70static int ks7010_sdio_write(struct ks_wlan_private *priv, unsigned int address,
71 unsigned char *buffer, int length)
72{
73 struct ks_sdio_card *card;
74 int rc;
75
76 card = priv->ks_wlan_hw.sdio_card;
77
78 if (length == 1) /* CMD52 */
79 sdio_writeb(card->func, *buffer, (unsigned int)address, &rc);
80 else /* CMD53 */
81 rc = sdio_memcpy_toio(card->func, (unsigned int)address, buffer,
82 length);
83
84 if (rc != 0)
85 DPRINTK(1, "sdio error=%d size=%d\n", rc, length);
86
87 return rc;
88}
89
feedcf1a 90void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv)
13a9930d
WS
91{
92 unsigned char rw_data;
93 int retval;
94
95 DPRINTK(4, "\n");
96
97 /* clear request */
cdf6ecc5 98 atomic_set(&priv->sleepstatus.doze_request, 0);
13a9930d 99
cdf6ecc5 100 if (atomic_read(&priv->sleepstatus.status) == 0) {
13a9930d 101 rw_data = GCR_B_DOZE;
cdf6ecc5
WS
102 retval =
103 ks7010_sdio_write(priv, GCR_B, &rw_data, sizeof(rw_data));
104 if (retval) {
13a9930d
WS
105 DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
106 goto out;
107 }
108 DPRINTK(4, "PMG SET!! : GCR_B=%02X\n", rw_data);
cdf6ecc5 109 DPRINTK(3, "sleep_mode=SLP_SLEEP\n");
13a9930d 110 atomic_set(&priv->sleepstatus.status, 1);
cdf6ecc5
WS
111 priv->last_doze = jiffies;
112 } else {
113 DPRINTK(1, "sleep_mode=%d\n", priv->sleep_mode);
13a9930d
WS
114 }
115
cdf6ecc5 116 out:
13a9930d 117 priv->sleep_mode = atomic_read(&priv->sleepstatus.status);
13a9930d
WS
118}
119
feedcf1a 120void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv)
13a9930d
WS
121{
122 unsigned char rw_data;
123 int retval;
124
125 DPRINTK(4, "\n");
126
127 /* clear request */
cdf6ecc5 128 atomic_set(&priv->sleepstatus.wakeup_request, 0);
13a9930d 129
cdf6ecc5 130 if (atomic_read(&priv->sleepstatus.status) == 1) {
13a9930d 131 rw_data = WAKEUP_REQ;
cdf6ecc5
WS
132 retval =
133 ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data));
134 if (retval) {
13a9930d
WS
135 DPRINTK(1, " error : WAKEUP=%02X\n", rw_data);
136 goto out;
137 }
138 DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data);
139 atomic_set(&priv->sleepstatus.status, 0);
cdf6ecc5 140 priv->last_wakeup = jiffies;
13a9930d 141 ++priv->wakeup_count;
cdf6ecc5
WS
142 } else {
143 DPRINTK(1, "sleep_mode=%d\n", priv->sleep_mode);
13a9930d
WS
144 }
145
cdf6ecc5 146 out:
13a9930d 147 priv->sleep_mode = atomic_read(&priv->sleepstatus.status);
13a9930d
WS
148}
149
feedcf1a 150void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv)
13a9930d
WS
151{
152 unsigned char rw_data;
153 int retval;
154
155 DPRINTK(4, "\n");
cdf6ecc5 156 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
13a9930d 157 rw_data = WAKEUP_REQ;
cdf6ecc5
WS
158 retval =
159 ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data));
160 if (retval) {
13a9930d
WS
161 DPRINTK(1, " error : WAKEUP=%02X\n", rw_data);
162 }
163 DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data);
cdf6ecc5 164 priv->last_wakeup = jiffies;
13a9930d 165 ++priv->wakeup_count;
cdf6ecc5
WS
166 } else {
167 DPRINTK(1, "psstatus=%d\n",
168 atomic_read(&priv->psstatus.status));
13a9930d
WS
169 }
170}
171
feedcf1a 172int _ks_wlan_hw_power_save(struct ks_wlan_private *priv)
13a9930d 173{
cdf6ecc5 174 int rc = 0;
13a9930d
WS
175 unsigned char rw_data;
176 int retval;
177
cdf6ecc5 178 if (priv->reg.powermgt == POWMGT_ACTIVE_MODE)
13a9930d
WS
179 return rc;
180
cdf6ecc5
WS
181 if (priv->reg.operation_mode == MODE_INFRASTRUCTURE &&
182 (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {
13a9930d
WS
183
184 //DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status));
cdf6ecc5
WS
185 if (priv->dev_state == DEVICE_STATE_SLEEP) {
186 switch (atomic_read(&priv->psstatus.status)) {
187 case PS_SNOOZE: /* 4 */
188 break;
189 default:
190 DPRINTK(5, "\npsstatus.status=%d\npsstatus.confirm_wait=%d\npsstatus.snooze_guard=%d\ncnt_txqbody=%d\n",
191 atomic_read(&priv->psstatus.status),
192 atomic_read(&priv->psstatus.confirm_wait),
193 atomic_read(&priv->psstatus.snooze_guard),
194 cnt_txqbody(priv));
195
196 if (!atomic_read(&priv->psstatus.confirm_wait)
197 && !atomic_read(&priv->psstatus.snooze_guard)
198 && !cnt_txqbody(priv)) {
199 retval =
200 ks7010_sdio_read(priv, INT_PENDING,
201 &rw_data,
202 sizeof(rw_data));
203 if (retval) {
204 DPRINTK(1,
205 " error : INT_PENDING=%02X\n",
206 rw_data);
207 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
208 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
209 break;
210 }
cdf6ecc5
WS
211 if (!rw_data) {
212 rw_data = GCR_B_DOZE;
213 retval =
214 ks7010_sdio_write(priv,
215 GCR_B,
216 &rw_data,
217 sizeof(rw_data));
218 if (retval) {
219 DPRINTK(1,
220 " error : GCR_B=%02X\n",
221 rw_data);
222 queue_delayed_work
223 (priv->ks_wlan_hw.ks7010sdio_wq,
224 &priv->ks_wlan_hw.rw_wq, 1);
225 break;
226 }
227 DPRINTK(4,
228 "PMG SET!! : GCR_B=%02X\n",
229 rw_data);
230 atomic_set(&priv->psstatus.
231 status, PS_SNOOZE);
232 DPRINTK(3,
233 "psstatus.status=PS_SNOOZE\n");
234 } else {
235 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
236 &priv->ks_wlan_hw.rw_wq, 1);
237 }
238 } else {
239 queue_delayed_work(priv->ks_wlan_hw.
240 ks7010sdio_wq,
241 &priv->ks_wlan_hw.rw_wq,
242 0);
13a9930d 243 }
cdf6ecc5 244 break;
13a9930d 245 }
13a9930d 246 }
13a9930d
WS
247
248 }
249
250 return rc;
251}
252
feedcf1a 253int ks_wlan_hw_power_save(struct ks_wlan_private *priv)
13a9930d 254{
cdf6ecc5
WS
255 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
256 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
257 return 0;
258}
259
cdf6ecc5
WS
260static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p,
261 unsigned long size,
262 void (*complete_handler) (void *arg1, void *arg2),
263 void *arg1, void *arg2)
13a9930d
WS
264{
265 struct tx_device_buffer *sp;
266
267 if (priv->dev_state < DEVICE_STATE_BOOT) {
268 kfree(p);
269 if (complete_handler != NULL)
cdf6ecc5 270 (*complete_handler) (arg1, arg2);
13a9930d
WS
271 return 1;
272 }
273
cdf6ecc5 274 if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) {
13a9930d 275 /* in case of buffer overflow */
cdf6ecc5 276 DPRINTK(1, "tx buffer overflow\n");
13a9930d
WS
277 kfree(p);
278 if (complete_handler != NULL)
cdf6ecc5 279 (*complete_handler) (arg1, arg2);
13a9930d
WS
280 return 1;
281 }
282
283 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qtail];
284 sp->sendp = p;
285 sp->size = size;
286 sp->complete_handler = complete_handler;
287 sp->arg1 = arg1;
288 sp->arg2 = arg2;
289 inc_txqtail(priv);
290
291 return 0;
292}
293
294/* write data */
cdf6ecc5
WS
295static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer,
296 unsigned long size)
13a9930d 297{
695872ea 298 int retval;
13a9930d
WS
299 unsigned char rw_data;
300 struct hostif_hdr *hdr;
301 hdr = (struct hostif_hdr *)buffer;
13a9930d 302
cdf6ecc5
WS
303 DPRINTK(4, "size=%d\n", hdr->size);
304 if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
305 DPRINTK(1, "unknown event=%04X\n", hdr->event);
13a9930d
WS
306 return 0;
307 }
308
309 retval = ks7010_sdio_write(priv, DATA_WINDOW, buffer, size);
cdf6ecc5 310 if (retval) {
13a9930d
WS
311 DPRINTK(1, " write error : retval=%d\n", retval);
312 return -4;
313 }
314
315 rw_data = WRITE_STATUS_BUSY;
cdf6ecc5
WS
316 retval =
317 ks7010_sdio_write(priv, WRITE_STATUS, &rw_data, sizeof(rw_data));
318 if (retval) {
13a9930d
WS
319 DPRINTK(1, " error : WRITE_STATUS=%02X\n", rw_data);
320 return -3;
321 }
322
323 return 0;
324}
325
326static void tx_device_task(void *dev)
327{
feedcf1a 328 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
cdf6ecc5 329 struct tx_device_buffer *sp;
13a9930d
WS
330 int rc = 0;
331
332 DPRINTK(4, "\n");
cdf6ecc5
WS
333 if (cnt_txqbody(priv) > 0
334 && atomic_read(&priv->psstatus.status) != PS_SNOOZE) {
13a9930d 335 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
cdf6ecc5 336 if (priv->dev_state >= DEVICE_STATE_BOOT) {
13a9930d 337 rc = write_to_device(priv, sp->sendp, sp->size);
cdf6ecc5
WS
338 if (rc) {
339 DPRINTK(1, "write_to_device error !!(%d)\n",
340 rc);
341 queue_delayed_work(priv->ks_wlan_hw.
342 ks7010sdio_wq,
343 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
344 return;
345 }
346
347 }
cdf6ecc5
WS
348 kfree(sp->sendp); /* allocated memory free */
349 if (sp->complete_handler != NULL) /* TX Complete */
350 (*sp->complete_handler) (sp->arg1, sp->arg2);
13a9930d
WS
351 inc_txqhead(priv);
352
cdf6ecc5
WS
353 if (cnt_txqbody(priv) > 0) {
354 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
355 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
356 }
357 }
13a9930d
WS
358}
359
cdf6ecc5
WS
360int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
361 void (*complete_handler) (void *arg1, void *arg2),
362 void *arg1, void *arg2)
13a9930d 363{
cdf6ecc5 364 int result = 0;
13a9930d
WS
365 struct hostif_hdr *hdr;
366 hdr = (struct hostif_hdr *)p;
367
cdf6ecc5
WS
368 if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
369 DPRINTK(1, "unknown event=%04X\n", hdr->event);
13a9930d
WS
370 return 0;
371 }
372
373 /* add event to hostt buffer */
374 priv->hostt.buff[priv->hostt.qtail] = hdr->event;
cdf6ecc5 375 priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
13a9930d 376
cdf6ecc5 377 DPRINTK(4, "event=%04X\n", hdr->event);
13a9930d
WS
378 spin_lock(&priv->tx_dev.tx_dev_lock);
379 result = enqueue_txdev(priv, p, size, complete_handler, arg1, arg2);
380 spin_unlock(&priv->tx_dev.tx_dev_lock);
381
cdf6ecc5
WS
382 if (cnt_txqbody(priv) > 0) {
383 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
384 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
385 }
386 return result;
387}
388
389static void rx_event_task(unsigned long dev)
390{
cdf6ecc5
WS
391 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
392 struct rx_device_buffer *rp;
13a9930d 393
cdf6ecc5 394 DPRINTK(4, "\n");
13a9930d 395
cdf6ecc5 396 if (cnt_rxqbody(priv) > 0 && priv->dev_state >= DEVICE_STATE_BOOT) {
13a9930d
WS
397 rp = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qhead];
398 hostif_receive(priv, rp->data, rp->size);
399 inc_rxqhead(priv);
400
cdf6ecc5 401 if (cnt_rxqbody(priv) > 0) {
13a9930d
WS
402 tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task);
403 }
404 }
13a9930d
WS
405}
406
407static void ks_wlan_hw_rx(void *dev, uint16_t size)
408{
feedcf1a 409 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
13a9930d
WS
410 int retval;
411 struct rx_device_buffer *rx_buffer;
412 struct hostif_hdr *hdr;
cdf6ecc5
WS
413 unsigned char read_status;
414 unsigned short event = 0;
13a9930d 415
cdf6ecc5 416 DPRINTK(4, "\n");
13a9930d
WS
417
418 /* receive data */
cdf6ecc5 419 if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
13a9930d 420 /* in case of buffer overflow */
cdf6ecc5 421 DPRINTK(1, "rx buffer overflow \n");
13a9930d
WS
422 goto error_out;
423 }
424 rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail];
425
cdf6ecc5
WS
426 retval =
427 ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0],
428 hif_align_size(size));
429 if (retval) {
13a9930d
WS
430 goto error_out;
431 }
432
433 /* length check */
cdf6ecc5 434 if (size > 2046 || size == 0) {
3215bb1a
WS
435#ifdef KS_WLAN_DEBUG
436 if (KS_WLAN_DEBUG > 5)
cdf6ecc5
WS
437 print_hex_dump_bytes("INVALID DATA dump: ",
438 DUMP_PREFIX_OFFSET,
3215bb1a
WS
439 rx_buffer->data, 32);
440#endif
13a9930d
WS
441 /* rx_status update */
442 read_status = READ_STATUS_IDLE;
cdf6ecc5
WS
443 retval =
444 ks7010_sdio_write(priv, READ_STATUS, &read_status,
445 sizeof(read_status));
446 if (retval) {
13a9930d
WS
447 DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
448 }
449 goto error_out;
450 }
451
452 hdr = (struct hostif_hdr *)&rx_buffer->data[0];
453 rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size);
454 event = hdr->event;
455 inc_rxqtail(priv);
456
457 /* read status update */
458 read_status = READ_STATUS_IDLE;
cdf6ecc5
WS
459 retval =
460 ks7010_sdio_write(priv, READ_STATUS, &read_status,
461 sizeof(read_status));
462 if (retval) {
13a9930d
WS
463 DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
464 }
465 DPRINTK(4, "READ_STATUS=%02X\n", read_status);
466
cdf6ecc5
WS
467 if (atomic_read(&priv->psstatus.confirm_wait)) {
468 if (IS_HIF_CONF(event)) {
13a9930d
WS
469 DPRINTK(4, "IS_HIF_CONF true !!\n");
470 atomic_dec(&priv->psstatus.confirm_wait);
471 }
472 }
473
474 /* rx_event_task((void *)priv); */
475 tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task);
476
cdf6ecc5 477 error_out:
13a9930d
WS
478 return;
479}
480
481static void ks7010_rw_function(struct work_struct *work)
482{
483 struct hw_info_t *hw;
484 struct ks_wlan_private *priv;
485 unsigned char rw_data;
486 int retval;
487
488 hw = container_of(work, struct hw_info_t, rw_wq.work);
489 priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw);
490
cdf6ecc5 491 DPRINTK(4, "\n");
13a9930d 492
cdf6ecc5
WS
493 /* wiat after DOZE */
494 if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) {
495 DPRINTK(4, "wait after DOZE \n");
496 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
497 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
498 return;
499 }
500
501 /* wiat after WAKEUP */
cdf6ecc5 502 while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) {
13a9930d
WS
503 DPRINTK(4, "wait after WAKEUP \n");
504/* queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq,
505 (priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/
cdf6ecc5
WS
506 printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000,
507 jiffies);
13a9930d
WS
508 msleep(30);
509 }
510
511 sdio_claim_host(priv->ks_wlan_hw.sdio_card->func);
512
513 /* power save wakeup */
cdf6ecc5
WS
514 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
515 if (cnt_txqbody(priv) > 0) {
13a9930d 516 ks_wlan_hw_wakeup_request(priv);
cdf6ecc5
WS
517 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
518 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
519 }
520 goto err_out;
521 }
522
523 /* sleep mode doze */
cdf6ecc5 524 if (atomic_read(&priv->sleepstatus.doze_request) == 1) {
13a9930d
WS
525 ks_wlan_hw_sleep_doze_request(priv);
526 goto err_out;
527 }
528 /* sleep mode wakeup */
cdf6ecc5 529 if (atomic_read(&priv->sleepstatus.wakeup_request) == 1) {
13a9930d
WS
530 ks_wlan_hw_sleep_wakeup_request(priv);
531 goto err_out;
532 }
533
534 /* read (WriteStatus/ReadDataSize FN1:00_0014) */
cdf6ecc5
WS
535 retval =
536 ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data));
537 if (retval) {
538 DPRINTK(1, " error : WSTATUS_RSIZE=%02X psstatus=%d\n", rw_data,
539 atomic_read(&priv->psstatus.status));
13a9930d
WS
540 goto err_out;
541 }
542 DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
543
cdf6ecc5
WS
544 if (rw_data & RSIZE_MASK) { /* Read schedule */
545 ks_wlan_hw_rx((void *)priv,
546 (uint16_t) (((rw_data & RSIZE_MASK) << 4)));
13a9930d 547 }
cdf6ecc5 548 if ((rw_data & WSTATUS_MASK)) {
13a9930d
WS
549 tx_device_task((void *)priv);
550 }
551 _ks_wlan_hw_power_save(priv);
552
cdf6ecc5 553 err_out:
13a9930d 554 sdio_release_host(priv->ks_wlan_hw.sdio_card->func);
13a9930d
WS
555}
556
13a9930d
WS
557static void ks_sdio_interrupt(struct sdio_func *func)
558{
559 int retval;
560 struct ks_sdio_card *card;
feedcf1a 561 struct ks_wlan_private *priv;
13a9930d
WS
562 unsigned char status, rsize, rw_data;
563
564 card = sdio_get_drvdata(func);
565 priv = card->priv;
566 DPRINTK(4, "\n");
567
cdf6ecc5
WS
568 if (priv->dev_state >= DEVICE_STATE_BOOT) {
569 retval =
570 ks7010_sdio_read(priv, INT_PENDING, &status,
571 sizeof(status));
572 if (retval) {
573 DPRINTK(1, "read INT_PENDING Failed!!(%d)\n", retval);
13a9930d
WS
574 goto intr_out;
575 }
576 DPRINTK(4, "INT_PENDING=%02X\n", rw_data);
577
578 /* schedule task for interrupt status */
579 /* bit7 -> Write General Communication B register */
580 /* read (General Communication B register) */
581 /* bit5 -> Write Status Idle */
582 /* bit2 -> Read Status Busy */
cdf6ecc5
WS
583 if (status & INT_GCR_B
584 || atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
585 retval =
586 ks7010_sdio_read(priv, GCR_B, &rw_data,
587 sizeof(rw_data));
588 if (retval) {
13a9930d
WS
589 DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
590 goto intr_out;
591 }
592 /* DPRINTK(1, "GCR_B=%02X\n", rw_data); */
cdf6ecc5
WS
593 if (rw_data == GCR_B_ACTIVE) {
594 if (atomic_read(&priv->psstatus.status) ==
595 PS_SNOOZE) {
596 atomic_set(&priv->psstatus.status,
597 PS_WAKEUP);
598 priv->wakeup_count = 0;
13a9930d
WS
599 }
600 complete(&priv->psstatus.wakeup_wait);
601 }
602
13a9930d
WS
603 }
604
cdf6ecc5 605 do {
13a9930d 606 /* read (WriteStatus/ReadDataSize FN1:00_0014) */
cdf6ecc5
WS
607 retval =
608 ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data,
609 sizeof(rw_data));
610 if (retval) {
611 DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n",
612 rw_data);
13a9930d
WS
613 goto intr_out;
614 }
615 DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
cdf6ecc5
WS
616 rsize = rw_data & RSIZE_MASK;
617 if (rsize) { /* Read schedule */
618 ks_wlan_hw_rx((void *)priv,
619 (uint16_t) (((rsize) << 4)));
13a9930d 620 }
cdf6ecc5 621 if (rw_data & WSTATUS_MASK) {
13a9930d 622#if 0
cdf6ecc5
WS
623 if (status & INT_WRITE_STATUS
624 && !cnt_txqbody(priv)) {
13a9930d 625 /* dummy write for interrupt clear */
cdf6ecc5
WS
626 rw_data = 0;
627 retval =
628 ks7010_sdio_write(priv, DATA_WINDOW,
629 &rw_data,
630 sizeof(rw_data));
13a9930d 631 if (retval) {
cdf6ecc5
WS
632 DPRINTK(1,
633 "write DATA_WINDOW Failed!!(%d)\n",
634 retval);
13a9930d
WS
635 }
636 status &= ~INT_WRITE_STATUS;
cdf6ecc5 637 } else {
13a9930d 638#endif
cdf6ecc5
WS
639 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
640 if (cnt_txqbody(priv)) {
13a9930d 641 ks_wlan_hw_wakeup_request(priv);
cdf6ecc5
WS
642 queue_delayed_work
643 (priv->ks_wlan_hw.
644 ks7010sdio_wq,
645 &priv->ks_wlan_hw.
646 rw_wq, 1);
13a9930d
WS
647 return;
648 }
cdf6ecc5 649 } else {
13a9930d
WS
650 tx_device_task((void *)priv);
651 }
cdf6ecc5
WS
652#if 0
653 }
654#endif
13a9930d 655 }
cdf6ecc5 656 } while (rsize);
13a9930d
WS
657 }
658
cdf6ecc5
WS
659 intr_out:
660 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
661 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
662}
663
cdf6ecc5 664static int trx_device_init(struct ks_wlan_private *priv)
13a9930d
WS
665{
666 /* initialize values (tx) */
667 priv->tx_dev.qtail = priv->tx_dev.qhead = 0;
668
669 /* initialize values (rx) */
670 priv->rx_dev.qtail = priv->rx_dev.qhead = 0;
671
672 /* initialize spinLock (tx,rx) */
673 spin_lock_init(&priv->tx_dev.tx_dev_lock);
674 spin_lock_init(&priv->rx_dev.rx_dev_lock);
675
cdf6ecc5
WS
676 tasklet_init(&priv->ks_wlan_hw.rx_bh_task, rx_event_task,
677 (unsigned long)priv);
13a9930d
WS
678
679 return 0;
680}
681
cdf6ecc5 682static void trx_device_exit(struct ks_wlan_private *priv)
13a9930d 683{
cdf6ecc5 684 struct tx_device_buffer *sp;
13a9930d
WS
685
686 /* tx buffer clear */
cdf6ecc5 687 while (cnt_txqbody(priv) > 0) {
13a9930d 688 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
cdf6ecc5
WS
689 kfree(sp->sendp); /* allocated memory free */
690 if (sp->complete_handler != NULL) /* TX Complete */
691 (*sp->complete_handler) (sp->arg1, sp->arg2);
13a9930d
WS
692 inc_txqhead(priv);
693 }
694
695 tasklet_kill(&priv->ks_wlan_hw.rx_bh_task);
13a9930d 696}
cdf6ecc5 697
feedcf1a 698static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index)
13a9930d 699{
cdf6ecc5 700 int rc = 0;
13a9930d
WS
701 int retval;
702 unsigned char *data_buf;
13a9930d
WS
703
704 data_buf = kmalloc(sizeof(u32), GFP_KERNEL);
cdf6ecc5
WS
705 if (!data_buf) {
706 rc = 1;
707 goto error_out;
708 }
13a9930d
WS
709
710 memcpy(data_buf, &index, sizeof(index));
711 retval = ks7010_sdio_write(priv, WRITE_INDEX, data_buf, sizeof(index));
cdf6ecc5
WS
712 if (retval) {
713 rc = 2;
714 goto error_out;
715 }
13a9930d
WS
716
717 retval = ks7010_sdio_write(priv, READ_INDEX, data_buf, sizeof(index));
cdf6ecc5
WS
718 if (retval) {
719 rc = 3;
720 goto error_out;
721 }
722 error_out:
58043f25 723 kfree(data_buf);
13a9930d
WS
724 return rc;
725}
726
727#define ROM_BUFF_SIZE (64*1024)
feedcf1a 728static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address,
13a9930d
WS
729 unsigned char *data, unsigned int size)
730{
cdf6ecc5 731 int rc = 0;
13a9930d
WS
732 int retval;
733 unsigned char *read_buf;
eeed92c0 734
13a9930d 735 read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
cdf6ecc5
WS
736 if (!read_buf) {
737 rc = 1;
738 goto error_out;
739 }
13a9930d 740 retval = ks7010_sdio_read(priv, address, read_buf, size);
cdf6ecc5
WS
741 if (retval) {
742 rc = 2;
743 goto error_out;
744 }
13a9930d
WS
745 retval = memcmp(data, read_buf, size);
746
cdf6ecc5
WS
747 if (retval) {
748 DPRINTK(0, "data compare error (%d) \n", retval);
749 rc = 3;
750 goto error_out;
13a9930d 751 }
cdf6ecc5 752 error_out:
58043f25 753 kfree(read_buf);
13a9930d
WS
754 return rc;
755}
cdf6ecc5 756
c4730a92 757static int ks7010_upload_firmware(struct ks_wlan_private *priv,
cdf6ecc5 758 struct ks_sdio_card *card)
13a9930d 759{
cdf6ecc5
WS
760 unsigned int size, offset, n = 0;
761 unsigned char *rom_buf;
762 unsigned char rw_data = 0;
763 int retval, rc = 0;
13a9930d
WS
764 int length;
765 const struct firmware *fw_entry = NULL;
13a9930d 766
13a9930d
WS
767 /* buffer allocate */
768 rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
369e1b69
SM
769 if (!rom_buf)
770 return 3;
13a9930d
WS
771
772 sdio_claim_host(card->func);
773
774 /* Firmware running ? */
775 retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
cdf6ecc5
WS
776 if (rw_data == GCR_A_RUN) {
777 DPRINTK(0, "MAC firmware running ...\n");
13a9930d
WS
778 rc = 0;
779 goto error_out0;
780 }
781
6ee9169b
WS
782 retval = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev);
783 if (retval)
b80cfea2 784 goto error_out0;
6ee9169b 785
13a9930d 786 length = fw_entry->size;
13a9930d
WS
787
788 /* Load Program */
789 n = 0;
cdf6ecc5
WS
790 do {
791 if (length >= ROM_BUFF_SIZE) {
13a9930d
WS
792 size = ROM_BUFF_SIZE;
793 length = length - ROM_BUFF_SIZE;
cdf6ecc5
WS
794 } else {
795 size = length;
796 length = 0;
13a9930d 797 }
cdf6ecc5
WS
798 DPRINTK(4, "size = %d\n", size);
799 if (size == 0)
800 break;
801 memcpy(rom_buf, fw_entry->data + n, size);
13a9930d
WS
802 /* Update write index */
803 offset = n;
cdf6ecc5
WS
804 retval =
805 ks7010_sdio_update_index(priv,
806 KS7010_IRAM_ADDRESS + offset);
807 if (retval) {
808 rc = 6;
809 goto error_out1;
810 }
13a9930d
WS
811
812 /* Write data */
813 retval = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size);
cdf6ecc5
WS
814 if (retval) {
815 rc = 8;
816 goto error_out1;
817 }
13a9930d
WS
818
819 /* compare */
cdf6ecc5
WS
820 retval =
821 ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size);
822 if (retval) {
823 rc = 9;
824 goto error_out1;
825 }
13a9930d
WS
826 n += size;
827
cdf6ecc5 828 } while (size);
13a9930d
WS
829
830 /* Remap request */
831 rw_data = GCR_A_REMAP;
832 retval = ks7010_sdio_write(priv, GCR_A, &rw_data, sizeof(rw_data));
cdf6ecc5 833 if (retval) {
13a9930d
WS
834 rc = 11;
835 goto error_out1;
836 }
cdf6ecc5 837 DPRINTK(4, " REMAP Request : GCR_A=%02X\n", rw_data);
13a9930d
WS
838
839 /* Firmware running check */
840 for (n = 0; n < 50; ++n) {
cdf6ecc5
WS
841 mdelay(10); /* wait_ms(10); */
842 retval =
843 ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
844 if (retval) {
845 rc = 11;
846 goto error_out1;
847 }
848 if (rw_data == GCR_A_RUN)
849 break;
13a9930d 850 }
cdf6ecc5 851 DPRINTK(4, "firmware wakeup (%d)!!!!\n", n);
13a9930d
WS
852 if ((50) <= n) {
853 DPRINTK(1, "firmware can't start\n");
cdf6ecc5 854 rc = 12;
13a9930d
WS
855 goto error_out1;
856 }
857
858 rc = 0;
859
13a9930d
WS
860 error_out1:
861 release_firmware(fw_entry);
13a9930d
WS
862 error_out0:
863 sdio_release_host(card->func);
58043f25 864 kfree(rom_buf);
13a9930d
WS
865 return rc;
866}
867
e8593a8a 868static void ks7010_card_init(struct ks_wlan_private *priv)
13a9930d 869{
cdf6ecc5 870 DPRINTK(5, "\ncard_init_task()\n");
13a9930d
WS
871
872 /* init_waitqueue_head(&priv->confirm_wait); */
873 init_completion(&priv->confirm_wait);
874
cdf6ecc5 875 DPRINTK(5, "init_completion()\n");
13a9930d
WS
876
877 /* get mac address & firmware version */
878 hostif_sme_enqueue(priv, SME_START);
879
cdf6ecc5 880 DPRINTK(5, "hostif_sme_enqueu()\n");
13a9930d 881
cdf6ecc5
WS
882 if (!wait_for_completion_interruptible_timeout
883 (&priv->confirm_wait, 5 * HZ)) {
884 DPRINTK(1, "wait time out!! SME_START\n");
13a9930d
WS
885 }
886
cdf6ecc5 887 if (priv->mac_address_valid && priv->version_size) {
13a9930d
WS
888 priv->dev_state = DEVICE_STATE_PREINIT;
889 }
890
891 hostif_sme_enqueue(priv, SME_GET_EEPROM_CKSUM);
892
893 /* load initial wireless parameter */
894 hostif_sme_enqueue(priv, SME_STOP_REQUEST);
895
896 hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_REQUEST);
897 hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_REQUEST);
898
899 hostif_sme_enqueue(priv, SME_WEP_INDEX_REQUEST);
900 hostif_sme_enqueue(priv, SME_WEP_KEY1_REQUEST);
901 hostif_sme_enqueue(priv, SME_WEP_KEY2_REQUEST);
902 hostif_sme_enqueue(priv, SME_WEP_KEY3_REQUEST);
903 hostif_sme_enqueue(priv, SME_WEP_KEY4_REQUEST);
904
905 hostif_sme_enqueue(priv, SME_WEP_FLAG_REQUEST);
906 hostif_sme_enqueue(priv, SME_RSN_ENABLED_REQUEST);
907 hostif_sme_enqueue(priv, SME_MODE_SET_REQUEST);
908 hostif_sme_enqueue(priv, SME_START_REQUEST);
909
cdf6ecc5
WS
910 if (!wait_for_completion_interruptible_timeout
911 (&priv->confirm_wait, 5 * HZ)) {
912 DPRINTK(1, "wait time out!! wireless parameter set\n");
13a9930d
WS
913 }
914
cdf6ecc5 915 if (priv->dev_state >= DEVICE_STATE_PREINIT) {
13a9930d
WS
916 DPRINTK(1, "DEVICE READY!!\n");
917 priv->dev_state = DEVICE_STATE_READY;
cdf6ecc5
WS
918 } else {
919 DPRINTK(1, "dev_state=%d\n", priv->dev_state);
13a9930d
WS
920 }
921}
922
6ee9169b
WS
923static void ks7010_init_defaults(struct ks_wlan_private *priv)
924{
925 priv->reg.tx_rate = TX_RATE_AUTO;
926 priv->reg.preamble = LONG_PREAMBLE;
927 priv->reg.powermgt = POWMGT_ACTIVE_MODE;
928 priv->reg.scan_type = ACTIVE_SCAN;
929 priv->reg.beacon_lost_count = 20;
930 priv->reg.rts = 2347UL;
931 priv->reg.fragment = 2346UL;
932 priv->reg.phy_type = D_11BG_COMPATIBLE_MODE;
933 priv->reg.cts_mode = CTS_MODE_FALSE;
934 priv->reg.rate_set.body[11] = TX_RATE_54M;
935 priv->reg.rate_set.body[10] = TX_RATE_48M;
936 priv->reg.rate_set.body[9] = TX_RATE_36M;
937 priv->reg.rate_set.body[8] = TX_RATE_18M;
938 priv->reg.rate_set.body[7] = TX_RATE_9M;
939 priv->reg.rate_set.body[6] = TX_RATE_24M | BASIC_RATE;
940 priv->reg.rate_set.body[5] = TX_RATE_12M | BASIC_RATE;
941 priv->reg.rate_set.body[4] = TX_RATE_6M | BASIC_RATE;
942 priv->reg.rate_set.body[3] = TX_RATE_11M | BASIC_RATE;
943 priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE;
944 priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE;
945 priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE;
946 priv->reg.tx_rate = TX_RATE_FULL_AUTO;
947 priv->reg.rate_set.size = 12;
948}
949
c4730a92 950static int ks7010_sdio_probe(struct sdio_func *func,
cdf6ecc5 951 const struct sdio_device_id *device)
13a9930d 952{
feedcf1a 953 struct ks_wlan_private *priv;
13a9930d
WS
954 struct ks_sdio_card *card;
955 struct net_device *netdev;
956 unsigned char rw_data;
2801d7a2 957 int ret;
13a9930d 958
c4730a92 959 DPRINTK(5, "ks7010_sdio_probe()\n");
13a9930d
WS
960
961 priv = NULL;
cdf6ecc5 962 netdev = NULL;
13a9930d
WS
963
964 /* initilize ks_sdio_card */
965 card = kzalloc(sizeof(struct ks_sdio_card), GFP_KERNEL);
966 if (!card)
967 return -ENOMEM;
968
cdf6ecc5 969 card->func = func;
13a9930d
WS
970 spin_lock_init(&card->lock);
971
13a9930d
WS
972 /*** Initialize SDIO ***/
973 sdio_claim_host(func);
974
975 /* bus setting */
976 /* Issue config request to override clock rate */
977
978 /* function blocksize set */
979 ret = sdio_set_block_size(func, KS7010_IO_BLOCK_SIZE);
cdf6ecc5
WS
980 DPRINTK(5, "multi_block=%d sdio_set_block_size()=%d %d\n",
981 func->card->cccr.multi_block, func->cur_blksize, ret);
13a9930d
WS
982
983 /* Allocate the slot current */
984
985 /* function enable */
986 ret = sdio_enable_func(func);
987 DPRINTK(5, "sdio_enable_func() %d\n", ret);
988 if (ret)
989 goto error_free_card;
990
991 /* interrupt disable */
cdf6ecc5 992 sdio_writeb(func, 0, INT_ENABLE, &ret);
13a9930d
WS
993 if (ret)
994 goto error_free_card;
cdf6ecc5 995 sdio_writeb(func, 0xff, INT_PENDING, &ret);
13a9930d
WS
996 if (ret)
997 goto error_disable_func;
998
999 /* setup interrupt handler */
1000 ret = sdio_claim_irq(func, ks_sdio_interrupt);
1001 if (ret)
1002 goto error_disable_func;
1003
1004 sdio_release_host(func);
1005
1006 sdio_set_drvdata(func, card);
1007
1008 DPRINTK(5, "class = 0x%X, vendor = 0x%X, "
cdf6ecc5 1009 "device = 0x%X\n", func->class, func->vendor, func->device);
13a9930d
WS
1010
1011 /* private memory allocate */
1012 netdev = alloc_etherdev(sizeof(*priv));
1013 if (netdev == NULL) {
c4730a92 1014 printk(KERN_ERR "ks7010 : Unable to alloc new net device\n");
13a9930d
WS
1015 goto error_release_irq;
1016 }
6634cff1 1017 if (dev_alloc_name(netdev, "wlan%d") < 0) {
c4730a92 1018 printk(KERN_ERR "ks7010 : Couldn't get name!\n");
13a9930d
WS
1019 goto error_free_netdev;
1020 }
1021
1022 priv = netdev_priv(netdev);
1023
1024 card->priv = priv;
1025 SET_NETDEV_DEV(netdev, &card->func->dev); /* for create sysfs symlinks */
1026
1027 /* private memory initialize */
1028 priv->ks_wlan_hw.sdio_card = card;
1029 init_completion(&priv->ks_wlan_hw.ks7010_sdio_wait);
1030 priv->ks_wlan_hw.read_buf = NULL;
1031 priv->ks_wlan_hw.read_buf = kmalloc(RX_DATA_SIZE, GFP_KERNEL);
cdf6ecc5 1032 if (!priv->ks_wlan_hw.read_buf) {
13a9930d
WS
1033 goto error_free_netdev;
1034 }
1035 priv->dev_state = DEVICE_STATE_PREBOOT;
1036 priv->net_dev = netdev;
1037 priv->firmware_version[0] = '\0';
1038 priv->version_size = 0;
1039 priv->last_doze = jiffies; /* set current jiffies */
1040 priv->last_wakeup = jiffies;
1041 memset(&priv->nstats, 0, sizeof(priv->nstats));
1042 memset(&priv->wstats, 0, sizeof(priv->wstats));
1043
1044 /* sleep mode */
cdf6ecc5
WS
1045 atomic_set(&priv->sleepstatus.doze_request, 0);
1046 atomic_set(&priv->sleepstatus.wakeup_request, 0);
1047 atomic_set(&priv->sleepstatus.wakeup_request, 0);
13a9930d
WS
1048
1049 trx_device_init(priv);
1050 hostif_init(priv);
cdf6ecc5 1051 ks_wlan_net_start(netdev);
13a9930d 1052
6ee9169b 1053 ks7010_init_defaults(priv);
13a9930d
WS
1054
1055 /* Upload firmware */
c4730a92 1056 ret = ks7010_upload_firmware(priv, card); /* firmware load */
cdf6ecc5
WS
1057 if (ret) {
1058 printk(KERN_ERR
c4730a92 1059 "ks7010: firmware load failed !! retern code = %d\n",
cdf6ecc5 1060 ret);
13a9930d
WS
1061 goto error_free_read_buf;
1062 }
1063
1064 /* interrupt setting */
1065 /* clear Interrupt status write (ARMtoSD_InterruptPending FN1:00_0024) */
1066 rw_data = 0xff;
1067 sdio_claim_host(func);
1068 ret = ks7010_sdio_write(priv, INT_PENDING, &rw_data, sizeof(rw_data));
1069 sdio_release_host(func);
cdf6ecc5 1070 if (ret) {
13a9930d
WS
1071 DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data);
1072 }
1073 DPRINTK(4, " clear Interrupt : INT_PENDING=%02X\n", rw_data);
1074
13a9930d 1075 /* enable ks7010sdio interrupt (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS) */
cdf6ecc5 1076 rw_data = (INT_GCR_B | INT_READ_STATUS | INT_WRITE_STATUS);
13a9930d
WS
1077 sdio_claim_host(func);
1078 ret = ks7010_sdio_write(priv, INT_ENABLE, &rw_data, sizeof(rw_data));
1079 sdio_release_host(func);
cdf6ecc5 1080 if (ret) {
13a9930d
WS
1081 DPRINTK(1, " error : INT_ENABLE=%02X\n", rw_data);
1082 }
1083 DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", rw_data);
1084 priv->dev_state = DEVICE_STATE_BOOT;
1085
1086 priv->ks_wlan_hw.ks7010sdio_wq = create_workqueue("ks7010sdio_wq");
cdf6ecc5 1087 if (!priv->ks_wlan_hw.ks7010sdio_wq) {
13a9930d
WS
1088 DPRINTK(1, "create_workqueue failed !!\n");
1089 goto error_free_read_buf;
1090 }
1091
13a9930d 1092 INIT_DELAYED_WORK(&priv->ks_wlan_hw.rw_wq, ks7010_rw_function);
e8593a8a 1093 ks7010_card_init(priv);
13a9930d 1094
3fb54d75
WS
1095 ret = register_netdev(priv->net_dev);
1096 if (ret)
1097 goto error_free_read_buf;
1098
13a9930d
WS
1099 return 0;
1100
cdf6ecc5 1101 error_free_read_buf:
13a9930d
WS
1102 kfree(priv->ks_wlan_hw.read_buf);
1103 priv->ks_wlan_hw.read_buf = NULL;
cdf6ecc5 1104 error_free_netdev:
13a9930d
WS
1105 free_netdev(priv->net_dev);
1106 card->priv = NULL;
cdf6ecc5 1107 error_release_irq:
13a9930d
WS
1108 sdio_claim_host(func);
1109 sdio_release_irq(func);
cdf6ecc5 1110 error_disable_func:
13a9930d 1111 sdio_disable_func(func);
cdf6ecc5 1112 error_free_card:
13a9930d
WS
1113 sdio_release_host(func);
1114 sdio_set_drvdata(func, NULL);
1115 kfree(card);
2801d7a2 1116
13a9930d
WS
1117 return -ENODEV;
1118}
1119
c4730a92 1120static void ks7010_sdio_remove(struct sdio_func *func)
13a9930d
WS
1121{
1122 int ret;
1123 struct ks_sdio_card *card;
1124 struct ks_wlan_private *priv;
c4730a92 1125 DPRINTK(1, "ks7010_sdio_remove()\n");
13a9930d
WS
1126
1127 card = sdio_get_drvdata(func);
1128
cdf6ecc5 1129 if (card == NULL)
13a9930d
WS
1130 return;
1131
1132 DPRINTK(1, "priv = card->priv\n");
1133 priv = card->priv;
cdf6ecc5 1134 if (priv) {
803394d0
CIK
1135 struct net_device *netdev = priv->net_dev;
1136
13a9930d
WS
1137 ks_wlan_net_stop(netdev);
1138 DPRINTK(1, "ks_wlan_net_stop\n");
1139
1140 /* interrupt disable */
1141 sdio_claim_host(func);
cdf6ecc5
WS
1142 sdio_writeb(func, 0, INT_ENABLE, &ret);
1143 sdio_writeb(func, 0xff, INT_PENDING, &ret);
13a9930d
WS
1144 sdio_release_host(func);
1145 DPRINTK(1, "interrupt disable\n");
1146
1147 /* send stop request to MAC */
1148 {
1149 struct hostif_stop_request_t *pp;
cdf6ecc5
WS
1150 pp = (struct hostif_stop_request_t *)
1151 kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL);
1152 if (pp == NULL) {
1153 DPRINTK(3, "allocate memory failed..\n");
1154 return; /* to do goto ni suru */
13a9930d 1155 }
cdf6ecc5
WS
1156 pp->header.size =
1157 cpu_to_le16((uint16_t)
1158 (sizeof(*pp) -
1159 sizeof(pp->header.size)));
1160 pp->header.event = cpu_to_le16((uint16_t) HIF_STOP_REQ);
13a9930d
WS
1161
1162 sdio_claim_host(func);
cdf6ecc5
WS
1163 write_to_device(priv, (unsigned char *)pp,
1164 hif_align_size(sizeof(*pp)));
13a9930d
WS
1165 sdio_release_host(func);
1166 kfree(pp);
1167 }
1168 DPRINTK(1, "STOP Req\n");
1169
cdf6ecc5 1170 if (priv->ks_wlan_hw.ks7010sdio_wq) {
13a9930d
WS
1171 flush_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);
1172 destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);
1173 }
cdf6ecc5
WS
1174 DPRINTK(1,
1175 "destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);\n");
13a9930d 1176
13a9930d
WS
1177 hostif_exit(priv);
1178 DPRINTK(1, "hostif_exit\n");
1179
3fb54d75 1180 unregister_netdev(netdev);
13a9930d
WS
1181
1182 trx_device_exit(priv);
58043f25 1183 kfree(priv->ks_wlan_hw.read_buf);
13a9930d
WS
1184 free_netdev(priv->net_dev);
1185 card->priv = NULL;
1186 }
1187
1188 sdio_claim_host(func);
1189 sdio_release_irq(func);
1190 DPRINTK(1, "sdio_release_irq()\n");
1191 sdio_disable_func(func);
1192 DPRINTK(1, "sdio_disable_func()\n");
1193 sdio_release_host(func);
1194
1195 sdio_set_drvdata(func, NULL);
1196
1197 kfree(card);
1198 DPRINTK(1, "kfree()\n");
1199
cdf6ecc5 1200 DPRINTK(5, " Bye !!\n");
13a9930d
WS
1201}
1202
4c0d46d2
WS
1203static struct sdio_driver ks7010_sdio_driver = {
1204 .name = "ks7010_sdio",
1205 .id_table = ks7010_sdio_ids,
1206 .probe = ks7010_sdio_probe,
1207 .remove = ks7010_sdio_remove,
1208};
1209
6b0cb0b0 1210module_driver(ks7010_sdio_driver, sdio_register_driver, sdio_unregister_driver);
e1240140
WS
1211MODULE_AUTHOR("Sang Engineering, Qi-Hardware, KeyStream");
1212MODULE_DESCRIPTION("Driver for KeyStream KS7010 based SDIO cards");
1213MODULE_LICENSE("GPL v2");
1214MODULE_FIRMWARE(ROM_FILE);
This page took 0.112295 seconds and 5 git commands to generate.