Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: chromeos/drivers/ath6kl/hif/sdio/linux_sdio/src/hif.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------
2 // <copyright file="hif.c" company="Atheros">
3 // Copyright (c) 2004-2008 Atheros Corporation. All rights reserved.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation;
8 //
9 // Software distributed under the License is distributed on an "AS
10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 // implied. See the License for the specific language governing
12 // rights and limitations under the License.
13 //
14 //
15 //------------------------------------------------------------------------------
16 //==============================================================================
17 // HIF layer reference implementation for Linux Native MMC stack
18 //
19 // Author(s): ="Atheros"
20 //==============================================================================
21 #include <linux/mmc/card.h>
22 #include <linux/mmc/sdio_func.h>
23 #include <linux/mmc/sdio_ids.h>
24 #include <linux/mmc/sdio.h>
25 #include <linux/kthread.h>
26
27 /* by default setup a bounce buffer for the data packets, if the underlying host controller driver
28 does not use DMA you may be able to skip this step and save the memory alloca tion and transfer time */
29 #define HIF_USE_DMA_BOUNCE_BUFFER 1
30 #include "hif_internal.h"
31 #define ATH_MODULE_NAME hif
32 #include "a_debug.h"
33
34
35 #if HIF_USE_DMA_BOUNCE_BUFFER
36 /* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host control lers assume the
37 * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack).
38 * virt_addr_valid check fails on stack memory.
39 */
40 #define BUFFER_NEEDS_BOUNCE(buffer) (((A_UINT32)(buffer) & 0x3) || !virt_addr_v alid((buffer)))
41 #else
42 #define BUFFER_NEEDS_BOUNCE(buffer) (FALSE)
43 #endif
44
45 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id);
46 static void hifDeviceRemoved(struct sdio_func *func);
47 static HIF_DEVICE *addHifDevice(struct sdio_func *func);
48 static HIF_DEVICE *getHifDevice(struct sdio_func *func);
49 static void delHifDevice(HIF_DEVICE * device);
50 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, uns igned char byte);
51
52 int reset_sdio_on_unload = 0;
53 module_param(reset_sdio_on_unload, int, 0644);
54
55 /* ------ Static Variables ------ */
56 static const struct sdio_device_id ar6k_id_table[] = {
57 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) },
58 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) },
59 { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) },
60 { /* null */ },
61 };
62 MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
63
64 static struct sdio_driver ar6k_driver = {
65 .name = "ar6k_wlan",
66 .id_table = ar6k_id_table,
67 .probe = hifDeviceInserted,
68 .remove = hifDeviceRemoved,
69 };
70 /* make sure we only unregister when registered. */
71 static int registered = 0;
72
73 OSDRV_CALLBACKS osdrvCallbacks;
74 extern A_UINT32 onebitmode;
75 extern A_UINT32 busspeedlow;
76 extern A_UINT32 debughif;
77
78 static BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device);
79 static void hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest);
80 static void ResetAllCards(void);
81
82 #ifdef DEBUG
83
84 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
85 "hif",
86 "(Linux MMC) Host Interconnect Framework",
87 ATH_DEBUG_MASK_DEFAULTS,
88 0,
89 NULL);
90
91 #endif
92
93
94 /* ------ Functions ------ */
95 A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
96 {
97 int status;
98 AR_DEBUG_ASSERT(callbacks != NULL);
99
100 A_REGISTER_MODULE_DEBUG_INFO(hif);
101
102 /* store the callback handlers */
103 osdrvCallbacks = *callbacks;
104
105 /* Register with bus driver core */
106 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n"));
107 registered = 1;
108 status = sdio_register_driver(&ar6k_driver);
109 AR_DEBUG_ASSERT(status==0);
110
111 if (status != 0) {
112 return A_ERROR;
113 }
114
115 return A_OK;
116
117 }
118
119 static A_STATUS
120 __HIFReadWrite(HIF_DEVICE *device,
121 A_UINT32 address,
122 A_UCHAR *buffer,
123 A_UINT32 length,
124 A_UINT32 request,
125 void *context)
126 {
127 A_UINT8 opcode;
128 A_STATUS status = A_OK;
129 int ret;
130 A_UINT8 *tbuffer;
131 A_BOOL bounced = FALSE;
132
133 AR_DEBUG_ASSERT(device != NULL);
134 AR_DEBUG_ASSERT(device->func != NULL);
135
136 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0 x%X)\n",
137 device, buffer, address));
138
139 do {
140 if (request & HIF_EXTENDED_IO) {
141 //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n") );
142 } else {
143 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
144 ("AR6000: Invalid command type: 0x%08x\n", request)) ;
145 status = A_EINVAL;
146 break;
147 }
148
149 if (request & HIF_BLOCK_BASIS) {
150 /* round to whole block length size */
151 length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE;
152 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
153 ("AR6000: Block mode (BlockLen: %d)\n",
154 length));
155 } else if (request & HIF_BYTE_BASIS) {
156 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
157 ("AR6000: Byte mode (BlockLen: %d)\n",
158 length));
159 } else {
160 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
161 ("AR6000: Invalid data mode: 0x%08x\n", request));
162 status = A_EINVAL;
163 break;
164 }
165
166 #if 0
167 /* useful for checking register accesses */
168 if (length & 0x3) {
169 A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, a ddr:0x%X, len:%d\n",
170 request & HIF_WRITE ? "write":"read", address, l ength);
171 }
172 #endif
173
174 if (request & HIF_WRITE) {
175 if ((address >= HIF_MBOX_START_ADDR(0)) &&
176 (address <= HIF_MBOX_END_ADDR(3)))
177 {
178
179 AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH);
180
181 /*
182 * Mailbox write. Adjust the address so that the last byte
183 * falls on the EOM address.
184 */
185 address += (HIF_MBOX_WIDTH - length);
186 }
187 }
188
189 if (request & HIF_FIXED_ADDRESS) {
190 opcode = CMD53_FIXED_ADDRESS;
191 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\ n", address));
192 } else if (request & HIF_INCREMENTAL_ADDRESS) {
193 opcode = CMD53_INCR_ADDRESS;
194 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address));
195 } else {
196 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
197 ("AR6000: Invalid address mode: 0x%08x\n", request)) ;
198 status = A_EINVAL;
199 break;
200 }
201
202 if (request & HIF_WRITE) {
203 #if HIF_USE_DMA_BOUNCE_BUFFER
204 if (BUFFER_NEEDS_BOUNCE(buffer)) {
205 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
206 tbuffer = device->dma_buffer;
207 /* copy the write data to the dma buffer */
208 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
209 memcpy(tbuffer, buffer, length);
210 bounced = TRUE;
211 } else {
212 tbuffer = buffer;
213 }
214 #else
215 tbuffer = buffer;
216 #endif
217 if (opcode == CMD53_FIXED_ADDRESS) {
218 ret = sdio_writesb(device->func, address, tbuffer, length);
219 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d addres s: 0x%X, len: %d, 0x%X\n",
220 ret, address, length, *(int *) tbuffer));
221 } else {
222 ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
223 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d addres s: 0x%X, len: %d, 0x%X\n",
224 ret, address, length, *(int *) tbuffer));
225 }
226 } else if (request & HIF_READ) {
227 #if HIF_USE_DMA_BOUNCE_BUFFER
228 if (BUFFER_NEEDS_BOUNCE(buffer)) {
229 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
230 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
231 tbuffer = device->dma_buffer;
232 bounced = TRUE;
233 } else {
234 tbuffer = buffer;
235 }
236 #else
237 tbuffer = buffer;
238 #endif
239 if (opcode == CMD53_FIXED_ADDRESS) {
240 ret = sdio_readsb(device->func, tbuffer, address, length);
241 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address : 0x%X, len: %d, 0x%X\n",
242 ret, address, length, *(int *) tbuffer));
243 } else {
244 ret = sdio_memcpy_fromio(device->func, tbuffer, address, length) ;
245 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address : 0x%X, len: %d, 0x%X\n",
246 ret, address, length, *(int *) tbuffer));
247 }
248 #if HIF_USE_DMA_BOUNCE_BUFFER
249 if (bounced) {
250 /* copy the read data from the dma buffer */
251 memcpy(buffer, tbuffer, length);
252 }
253 #endif
254 } else {
255 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
256 ("AR6000: Invalid direction: 0x%08x\n", request));
257 status = A_EINVAL;
258 break;
259 }
260
261 if (ret) {
262 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
263 ("AR6000: SDIO bus operation failed! MMC stack retur ned : %d \n", ret));
264 status = A_ERROR;
265 }
266 } while (FALSE);
267
268 return status;
269 }
270
271 /* queue a read/write request */
272 A_STATUS
273 HIFReadWrite(HIF_DEVICE *device,
274 A_UINT32 address,
275 A_UCHAR *buffer,
276 A_UINT32 length,
277 A_UINT32 request,
278 void *context)
279 {
280 A_STATUS status = A_OK;
281 unsigned long flags;
282 BUS_REQUEST *busrequest;
283 BUS_REQUEST *async;
284 BUS_REQUEST *active;
285
286 AR_DEBUG_ASSERT(device != NULL);
287 AR_DEBUG_ASSERT(device->func != NULL);
288
289 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,a ddress));
290
291 do {
292 if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){
293 /* serialize all requests through the async thread */
294 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n",
295 (request & HIF_ASYNCHRONOUS)?"Async":"Synch"));
296 busrequest = hifAllocateBusRequest(device);
297 if (busrequest == NULL) {
298 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
299 ("AR6000: no async bus requests available (%s, addr:0x%X, le n:%d) \n",
300 request & HIF_READ ? "READ":"WRITE", address, length));
301 return A_ERROR;
302 }
303 spin_lock_irqsave(&device->asynclock, flags);
304 busrequest->address = address;
305 busrequest->buffer = buffer;
306 busrequest->length = length;
307 busrequest->request = request;
308 busrequest->context = context;
309 /* add to async list */
310 active = device->asyncreq;
311 if (active == NULL) {
312 device->asyncreq = busrequest;
313 device->asyncreq->inusenext = NULL;
314 } else {
315 for (async = device->asyncreq;
316 async != NULL;
317 async = async->inusenext) {
318 active = async;
319 }
320 active->inusenext = busrequest;
321 busrequest->inusenext = NULL;
322 }
323 spin_unlock_irqrestore(&device->asynclock, flags);
324 if (request & HIF_SYNCHRONOUS) {
325 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%X \n", (unsigned int)busrequest));
326
327 /* wait for completion */
328 up(&device->sem_async);
329 if (down_interruptible(&busrequest->sem_req) != 0) {
330 /* interrupted, exit */
331 return A_ERROR;
332 } else {
333 A_STATUS status = busrequest->status;
334 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freei ng 0x%X: 0x%X\n",
335 (unsigned int)busrequest, busrequest->status));
336 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X \n", (unsigned int)request));
337 hifFreeBusRequest(device, busrequest);
338 return status;
339 }
340 } else {
341 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x% X\n", (unsigned int)busrequest));
342 up(&device->sem_async);
343 return A_PENDING;
344 }
345 } else {
346 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
347 ("AR6000: Invalid execution mode: 0x%08x\n", (unsign ed int)request));
348 status = A_EINVAL;
349 break;
350 }
351 } while(0);
352
353 return status;
354 }
355 /* thread to serialize all requests, both sync and async */
356 static int async_task(void *param)
357 {
358 HIF_DEVICE *device;
359 BUS_REQUEST *request;
360 A_STATUS status;
361 unsigned long flags;
362
363 device = (HIF_DEVICE *)param;
364 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
365 set_current_state(TASK_INTERRUPTIBLE);
366 while(!device->async_shutdown) {
367 /* wait for work */
368 if (down_interruptible(&device->sem_async) != 0) {
369 /* interrupted, exit */
370 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n" ));
371 break;
372 }
373 if (device->async_shutdown) {
374 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n"));
375 break;
376 }
377 /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */
378 sdio_claim_host(device->func);
379 spin_lock_irqsave(&device->asynclock, flags);
380 /* pull the request to work on */
381 while (device->asyncreq != NULL) {
382 request = device->asyncreq;
383 if (request->inusenext != NULL) {
384 device->asyncreq = request->inusenext;
385 } else {
386 device->asyncreq = NULL;
387 }
388 spin_unlock_irqrestore(&device->asynclock, flags);
389 /* call HIFReadWrite in sync mode to do the work */
390 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req : 0x%X\n", (unsigned int)request));
391 status = __HIFReadWrite(device, request->address, request->buffer,
392 request->length, request->request & ~HIF_SYNCH RONOUS, NULL);
393 if (request->request & HIF_ASYNCHRONOUS) {
394 void *context = request->context;
395 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing re q: 0x%X\n", (unsigned int)request));
396 hifFreeBusRequest(device, request);
397 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%X\n", (unsigned int)request));
398 device->htcCallbacks.rwCompletionHandler(context, status);
399 } else {
400 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req : 0x%X\n", (unsigned int)request));
401 request->status = status;
402 up(&request->sem_req);
403 }
404 spin_lock_irqsave(&device->asynclock, flags);
405 }
406 spin_unlock_irqrestore(&device->asynclock, flags);
407 sdio_release_host(device->func);
408 }
409
410 complete_and_exit(&device->async_completion, 0);
411 return 0;
412 }
413
414 A_STATUS
415 HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
416 void *config, A_UINT32 configLen)
417 {
418 A_UINT32 count;
419
420 switch(opcode) {
421 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
422 ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
423 ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
424 ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
425 ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
426 break;
427
428 case HIF_DEVICE_GET_MBOX_ADDR:
429 for (count = 0; count < 4; count ++) {
430 ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
431 }
432
433 if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) {
434 SetExtendedMboxWindowInfo((A_UINT16)device->func->device,
435 (HIF_DEVICE_MBOX_INFO *)config);
436 }
437
438 break;
439 case HIF_DEVICE_GET_IRQ_PROC_MODE:
440 *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ON LY;
441 break;
442 case HIF_DEVICE_GET_OS_DEVICE:
443 /* pass back a pointer to the SDIO function's "dev" struct */
444 ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->de v;
445 break;
446 default:
447 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
448 ("AR6000: Unsupported configuration opcode: %d\n", o pcode));
449 return A_ERROR;
450 }
451
452 return A_OK;
453 }
454
455 void
456 HIFShutDownDevice(HIF_DEVICE *device)
457 {
458 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
459 if (device != NULL) {
460 AR_DEBUG_ASSERT(device->func != NULL);
461 } else {
462 /* since we are unloading the driver anyways, reset all cards in cas e the SDIO card
463 * is externally powered and we are unloading the SDIO stack. This avoids the problem when
464 * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
465 * enumerated */
466 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\ n"));
467 ResetAllCards();
468
469 /* Unregister with bus driver core */
470 if (registered) {
471 registered = 0;
472 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
473 ("AR6000: Unregistering with the bus driver\n"));
474 sdio_unregister_driver(&ar6k_driver);
475 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
476 ("AR6000: Unregistered\n"));
477 }
478 }
479 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n"));
480 }
481
482 static void
483 hifIRQHandler(struct sdio_func *func)
484 {
485 A_STATUS status;
486 HIF_DEVICE *device;
487 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
488
489 device = getHifDevice(func);
490 /* release the host during ints so we can pick it back up when we process cm ds */
491 sdio_release_host(device->func);
492 status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
493 sdio_claim_host(device->func);
494 AR_DEBUG_ASSERT(status == A_OK);
495 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
496 }
497
498 /* handle HTC startup via thread*/
499 static int startup_task(void *param)
500 {
501 HIF_DEVICE *device;
502
503 device = (HIF_DEVICE *)param;
504 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
505 /* start up inform DRV layer */
506 if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) {
507 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
508 }
509 return 0;
510 }
511
512 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
513 {
514 int ret;
515 HIF_DEVICE * device;
516 int count;
517 struct task_struct* startup_task_struct;
518
519 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
520 ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X , Device ID: 0x%X, block size: 0x%X/0x%X\n",
521 func->num, func->vendor, func->device, func->max_blksize, f unc->cur_blksize));
522
523 addHifDevice(func);
524 device = getHifDevice(func);
525
526 spin_lock_init(&device->lock);
527
528 spin_lock_init(&device->asynclock);
529
530 /* enable the SDIO function */
531 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: claim\n"));
532 sdio_claim_host(func);
533 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: enable\n"));
534 /* give us some time to enable, in ms */
535 func->enable_timeout = 100;
536 ret = sdio_enable_func(func);
537 if (ret) {
538 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X, timeout: %d\n",
539 __FUNCTION__, ret, func->enable_timeou t));
540 sdio_release_host(func);
541 return ret;
542 }
543 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: set block size 0x%X\n", HIF_MBOX_ BLOCK_SIZE));
544 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
545 sdio_release_host(func);
546 if (ret) {
547 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block siz e 0x%x AR6K: 0x%X\n",
548 __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret ));
549 sdio_release_host(func);
550 return ret;
551 }
552 /* Initialize the bus requests to be used later */
553 A_MEMZERO(device->busRequest, sizeof(device->busRequest));
554 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
555 sema_init(&device->busRequest[count].sem_req, 0);
556 hifFreeBusRequest(device, &device->busRequest[count]);
557 }
558
559 /* create async I/O thread */
560 device->async_shutdown = 0;
561 device->async_task = kthread_create(async_task,
562 (void *)device,
563 "AR6K Async");
564 if (device->async_task == NULL) {
565 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n" , __FUNCTION__));
566 sdio_release_host(func);
567 return A_ERROR;
568 }
569 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
570 sema_init(&device->sem_async, 0);
571 wake_up_process(device->async_task );
572
573 /* create startup thread */
574 startup_task_struct = kthread_create(startup_task,
575 (void *)device,
576 "AR6K startup");
577 if (startup_task_struct == NULL) {
578 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create startup task\ n", __FUNCTION__));
579 sdio_release_host(func);
580 return A_ERROR;
581 }
582 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start startup task\n"));
583 wake_up_process(startup_task_struct);
584
585 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: return %d\n", ret));
586 return ret;
587 }
588
589
590 void
591 HIFAckInterrupt(HIF_DEVICE *device)
592 {
593 AR_DEBUG_ASSERT(device != NULL);
594
595 /* Acknowledge our function IRQ */
596 }
597
598 void
599 HIFUnMaskInterrupt(HIF_DEVICE *device)
600 {
601 int ret;;
602
603 AR_DEBUG_ASSERT(device != NULL);
604 AR_DEBUG_ASSERT(device->func != NULL);
605
606 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n"));
607
608 /* Register the IRQ Handler */
609 sdio_claim_host(device->func);
610 ret = sdio_claim_irq(device->func, hifIRQHandler);
611 sdio_release_host(device->func);
612 AR_DEBUG_ASSERT(ret == 0);
613 }
614
615 void HIFMaskInterrupt(HIF_DEVICE *device)
616 {
617 int ret;;
618
619 AR_DEBUG_ASSERT(device != NULL);
620 AR_DEBUG_ASSERT(device->func != NULL);
621
622 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n"));
623
624 /* Mask our function IRQ */
625 sdio_claim_host(device->func);
626 ret = sdio_release_irq(device->func);
627 sdio_release_host(device->func);
628 AR_DEBUG_ASSERT(ret == 0);
629 }
630
631 static BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
632 {
633 BUS_REQUEST *busrequest;
634 unsigned long flag;
635
636 /* Acquire lock */
637 spin_lock_irqsave(&device->lock, flag);
638
639 /* Remove first in list */
640 if((busrequest = device->s_busRequestFreeQueue) != NULL)
641 {
642 device->s_busRequestFreeQueue = busrequest->next;
643 }
644
645 /* Release lock */
646 spin_unlock_irqrestore(&device->lock, flag);
647 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", b usrequest));
648 return busrequest;
649 }
650
651 static void
652 hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
653 {
654 unsigned long flag;
655
656 AR_DEBUG_ASSERT(busrequest != NULL);
657 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busre quest));
658 /* Acquire lock */
659 spin_lock_irqsave(&device->lock, flag);
660
661
662 /* Insert first in list */
663 busrequest->next = device->s_busRequestFreeQueue;
664 busrequest->inusenext = NULL;
665 device->s_busRequestFreeQueue = busrequest;
666
667 /* Release lock */
668 spin_unlock_irqrestore(&device->lock, flag);
669 }
670
671 static void hifDeviceRemoved(struct sdio_func *func)
672 {
673 A_STATUS status = A_OK;
674 HIF_DEVICE *device;
675 int ret;
676 AR_DEBUG_ASSERT(func != NULL);
677
678 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
679 device = getHifDevice(func);
680 if (device->claimedContext != NULL) {
681 status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, dev ice);
682 }
683
684 if (device->async_task != NULL) {
685 init_completion(&device->async_completion);
686 device->async_shutdown = 1;
687 up(&device->sem_async);
688 wait_for_completion(&device->async_completion);
689 device->async_task = NULL;
690 }
691 /* Disable the card */
692 sdio_claim_host(device->func);
693 ret = sdio_disable_func(device->func);
694
695 if (reset_sdio_on_unload) {
696 int ret;
697 /* reset the SDIO interface. This is useful in automated testing where the card
698 * does not need to be removed at the end of the test. It is expected t hat the user will
699 * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */
700 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uni nitialized state \n"));
701
702 /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows acc ess
703 * to undefined registers in the range of: 0xF0-0xFF */
704
705 ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3) );
706 if (ret) {
707 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret) );
708 }
709 }
710
711 sdio_release_host(device->func);
712 delHifDevice(device);
713 AR_DEBUG_ASSERT(status == A_OK);
714 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
715 }
716
717
718 static HIF_DEVICE *
719 addHifDevice(struct sdio_func *func)
720 {
721 HIF_DEVICE *hifdevice;
722 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n"));
723 AR_DEBUG_ASSERT(func != NULL);
724 hifdevice = (HIF_DEVICE *)kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL);
725 AR_DEBUG_ASSERT(hifdevice != NULL);
726 #if HIF_USE_DMA_BOUNCE_BUFFER
727 hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
728 AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL);
729 #endif
730 hifdevice->func = func;
731 sdio_set_drvdata(func, hifdevice);
732 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice) );
733 return hifdevice;
734 }
735
736 static HIF_DEVICE *
737 getHifDevice(struct sdio_func *func)
738 {
739 AR_DEBUG_ASSERT(func != NULL);
740 return (HIF_DEVICE *)sdio_get_drvdata(func);
741 }
742
743 static void
744 delHifDevice(HIF_DEVICE * device)
745 {
746 AR_DEBUG_ASSERT(device!= NULL);
747 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
748 if (device->dma_buffer != NULL) {
749 kfree(device->dma_buffer);
750 }
751 kfree(device);
752 }
753
754 static void ResetAllCards(void)
755 {
756 }
757
758 void HIFClaimDevice(HIF_DEVICE *device, void *context)
759 {
760 device->claimedContext = context;
761 }
762
763 void HIFReleaseDevice(HIF_DEVICE *device)
764 {
765 device->claimedContext = NULL;
766 }
767
768 A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks)
769 {
770 if (device->htcCallbacks.context != NULL) {
771 /* already in use! */
772 return A_ERROR;
773 }
774 device->htcCallbacks = *callbacks;
775 return A_OK;
776 }
777
778 void HIFDetachHTC(HIF_DEVICE *device)
779 {
780 A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
781 }
782
783 #define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
784 (arg) = (((rw) & 1) << 31) | \
785 (((func) & 0x7) << 28) | \
786 (((raw) & 1) << 27) | \
787 (1 << 26) | \
788 (((address) & 0x1FFFF) << 9) | \
789 (1 << 8) | \
790 ((writedata) & 0xFF)
791
792 #define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
793 SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00)
794 #define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
795 SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value)
796
797 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, uns igned char byte)
798 {
799 struct mmc_command ioCmd;
800 unsigned long arg;
801
802 memset(&ioCmd,0,sizeof(ioCmd));
803 SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte);
804 ioCmd.opcode = SD_IO_RW_DIRECT;
805 ioCmd.arg = arg;
806 ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
807
808 return mmc_wait_for_cmd(card->host, &ioCmd, 0);
809 }
810
811
812
813
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698