Root/drivers/staging/csr/sdio_mmc.c

1/*
2 * ---------------------------------------------------------------------------
3 *
4 * FILE: sdio_mmc.c
5 *
6 * PURPOSE: SDIO driver interface for generic MMC stack.
7 *
8 * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd.
9 *
10 * ---------------------------------------------------------------------------
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/mutex.h>
16#include <linux/gfp.h>
17
18#include <linux/mmc/core.h>
19#include <linux/mmc/card.h>
20#include <linux/mmc/host.h>
21#include <linux/mmc/sdio_func.h>
22#include <linux/mmc/sdio_ids.h>
23#include <linux/mmc/sdio.h>
24#include <linux/suspend.h>
25
26#include "unifi_priv.h"
27
28#ifdef ANDROID_BUILD
29struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */
30#endif
31
32static CsrSdioFunctionDriver *sdio_func_drv;
33
34#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
35#ifdef CONFIG_PM
36static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr);
37#endif
38
39/*
40 * We need to keep track of the power on/off because we can not call
41 * mmc_power_restore_host() when the card is already powered.
42 * Even then, we need to patch the MMC driver to add a power_restore handler
43 * in the mmc_sdio_ops structure. If the MMC driver before 2.6.37 is not patched,
44 * mmc_power_save_host() and mmc_power_restore_host() are no-ops in the kernel,
45 * returning immediately (at least on x86).
46 */
47static int card_is_powered = 1;
48#endif /* 2.6.32 */
49
50/* MMC uses ENOMEDIUM to indicate card gone away */
51
52static CsrResult
53ConvertSdioToCsrSdioResult(int r)
54{
55    CsrResult csrResult = CSR_RESULT_FAILURE;
56
57    switch (r) {
58    case 0:
59        csrResult = CSR_RESULT_SUCCESS;
60    break;
61    case -EIO:
62    case -EILSEQ:
63        csrResult = CSR_SDIO_RESULT_CRC_ERROR;
64    break;
65    /* Timeout errors */
66    case -ETIMEDOUT:
67    case -EBUSY:
68        csrResult = CSR_SDIO_RESULT_TIMEOUT;
69    break;
70    case -ENODEV:
71    case -ENOMEDIUM:
72        csrResult = CSR_SDIO_RESULT_NO_DEVICE;
73    break;
74    case -EINVAL:
75        csrResult = CSR_SDIO_RESULT_INVALID_VALUE;
76    break;
77    case -ENOMEM:
78    case -ENOSYS:
79    case -ERANGE:
80    case -ENXIO:
81        csrResult = CSR_RESULT_FAILURE;
82    break;
83    default:
84        unifi_warning(NULL, "Unrecognised SDIO error code: %d\n", r);
85    break;
86    }
87
88    return csrResult;
89}
90
91
92static int
93csr_io_rw_direct(struct mmc_card *card, int write, uint8_t fn,
94                 uint32_t addr, uint8_t in, uint8_t* out)
95{
96    struct mmc_command cmd;
97    int err;
98
99    BUG_ON(!card);
100    BUG_ON(fn > 7);
101
102    memset(&cmd, 0, sizeof(struct mmc_command));
103
104    cmd.opcode = SD_IO_RW_DIRECT;
105    cmd.arg = write ? 0x80000000 : 0x00000000;
106    cmd.arg |= fn << 28;
107    cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
108    cmd.arg |= addr << 9;
109    cmd.arg |= in;
110    cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
111
112    err = mmc_wait_for_cmd(card->host, &cmd, 0);
113    if (err)
114        return err;
115
116    /* this function is not exported, so we will need to sort it out here
117     * for now, lets hard code it to sdio */
118    if (0) {
119        /* old arg (mmc_host_is_spi(card->host)) { */
120        /* host driver already reported errors */
121    } else {
122        if (cmd.resp[0] & R5_ERROR) {
123            printk(KERN_ERR "%s: r5 error 0x%02x\n",
124                   __FUNCTION__, cmd.resp[0]);
125            return -EIO;
126        }
127        if (cmd.resp[0] & R5_FUNCTION_NUMBER)
128            return -EINVAL;
129        if (cmd.resp[0] & R5_OUT_OF_RANGE)
130            return -ERANGE;
131    }
132
133    if (out) {
134        if (0) { /* old argument (mmc_host_is_spi(card->host)) */
135            *out = (cmd.resp[0] >> 8) & 0xFF;
136        }
137        else {
138            *out = cmd.resp[0] & 0xFF;
139        }
140    }
141
142    return CSR_RESULT_SUCCESS;
143}
144
145
146CsrResult
147CsrSdioRead8(CsrSdioFunction *function, u32 address, u8 *data)
148{
149    struct sdio_func *func = (struct sdio_func *)function->priv;
150    int err = 0;
151
152    _sdio_claim_host(func);
153    *data = sdio_readb(func, address, &err);
154    _sdio_release_host(func);
155
156    if (err) {
157        func_exit_r(err);
158        return ConvertSdioToCsrSdioResult(err);
159    }
160
161    return CSR_RESULT_SUCCESS;
162} /* CsrSdioRead8() */
163
164CsrResult
165CsrSdioWrite8(CsrSdioFunction *function, u32 address, u8 data)
166{
167    struct sdio_func *func = (struct sdio_func *)function->priv;
168    int err = 0;
169
170    _sdio_claim_host(func);
171    sdio_writeb(func, data, address, &err);
172    _sdio_release_host(func);
173
174    if (err) {
175        func_exit_r(err);
176        return ConvertSdioToCsrSdioResult(err);
177    }
178
179    return CSR_RESULT_SUCCESS;
180} /* CsrSdioWrite8() */
181
182CsrResult
183CsrSdioRead16(CsrSdioFunction *function, u32 address, u16 *data)
184{
185    struct sdio_func *func = (struct sdio_func *)function->priv;
186    int err;
187    uint8_t b0, b1;
188
189    _sdio_claim_host(func);
190    b0 = sdio_readb(func, address, &err);
191    if (err) {
192        _sdio_release_host(func);
193        return ConvertSdioToCsrSdioResult(err);
194    }
195
196    b1 = sdio_readb(func, address+1, &err);
197    if (err) {
198        _sdio_release_host(func);
199        return ConvertSdioToCsrSdioResult(err);
200    }
201    _sdio_release_host(func);
202
203    *data = ((uint16_t)b1 << 8) | b0;
204
205    return CSR_RESULT_SUCCESS;
206} /* CsrSdioRead16() */
207
208
209CsrResult
210CsrSdioWrite16(CsrSdioFunction *function, u32 address, u16 data)
211{
212    struct sdio_func *func = (struct sdio_func *)function->priv;
213    int err;
214    uint8_t b0, b1;
215
216    _sdio_claim_host(func);
217    b1 = (data >> 8) & 0xFF;
218    sdio_writeb(func, b1, address+1, &err);
219    if (err) {
220        _sdio_release_host(func);
221        return ConvertSdioToCsrSdioResult(err);
222    }
223
224    b0 = data & 0xFF;
225    sdio_writeb(func, b0, address, &err);
226    if (err) {
227        _sdio_release_host(func);
228        return ConvertSdioToCsrSdioResult(err);
229    }
230
231    _sdio_release_host(func);
232    return CSR_RESULT_SUCCESS;
233} /* CsrSdioWrite16() */
234
235
236CsrResult
237CsrSdioF0Read8(CsrSdioFunction *function, u32 address, u8 *data)
238{
239    struct sdio_func *func = (struct sdio_func *)function->priv;
240    int err = 0;
241
242    _sdio_claim_host(func);
243#ifdef MMC_QUIRK_LENIENT_FN0
244    *data = sdio_f0_readb(func, address, &err);
245#else
246    err = csr_io_rw_direct(func->card, 0, 0, address, 0, data);
247#endif
248    _sdio_release_host(func);
249
250    if (err) {
251        func_exit_r(err);
252        return ConvertSdioToCsrSdioResult(err);
253    }
254
255    return CSR_RESULT_SUCCESS;
256} /* CsrSdioF0Read8() */
257
258CsrResult
259CsrSdioF0Write8(CsrSdioFunction *function, u32 address, u8 data)
260{
261    struct sdio_func *func = (struct sdio_func *)function->priv;
262    int err = 0;
263
264    _sdio_claim_host(func);
265#ifdef MMC_QUIRK_LENIENT_FN0
266    sdio_f0_writeb(func, data, address, &err);
267#else
268    err = csr_io_rw_direct(func->card, 1, 0, address, data, NULL);
269#endif
270    _sdio_release_host(func);
271
272    if (err) {
273        func_exit_r(err);
274        return ConvertSdioToCsrSdioResult(err);
275    }
276
277    return CSR_RESULT_SUCCESS;
278} /* CsrSdioF0Write8() */
279
280
281CsrResult
282CsrSdioRead(CsrSdioFunction *function, u32 address, void *data, u32 length)
283{
284    struct sdio_func *func = (struct sdio_func *)function->priv;
285    int err;
286
287    _sdio_claim_host(func);
288    err = sdio_readsb(func, data, address, length);
289    _sdio_release_host(func);
290
291    if (err) {
292        func_exit_r(err);
293        return ConvertSdioToCsrSdioResult(err);
294    }
295
296    return CSR_RESULT_SUCCESS;
297} /* CsrSdioRead() */
298
299CsrResult
300CsrSdioWrite(CsrSdioFunction *function, u32 address, const void *data, u32 length)
301{
302    struct sdio_func *func = (struct sdio_func *)function->priv;
303    int err;
304
305    _sdio_claim_host(func);
306    err = sdio_writesb(func, address, (void*)data, length);
307    _sdio_release_host(func);
308
309    if (err) {
310        func_exit_r(err);
311        return ConvertSdioToCsrSdioResult(err);
312    }
313
314    return CSR_RESULT_SUCCESS;
315} /* CsrSdioWrite() */
316
317
318static int
319csr_sdio_enable_hs(struct mmc_card *card)
320{
321    int ret;
322    u8 speed;
323
324    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) {
325        /* We've asked for HS clock rates, but controller doesn't
326         * claim to support it. We should limit the clock
327         * to 25MHz via module parameter.
328         */
329        printk(KERN_INFO "unifi: request HS but not MMC_CAP_SD_HIGHSPEED");
330        return 0;
331    }
332
333    if (!card->cccr.high_speed)
334        return 0;
335
336#if 1
337    ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
338    if (ret)
339        return ret;
340
341    speed |= SDIO_SPEED_EHS;
342#else
343    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
344    speed = SDIO_SPEED_EHS | SDIO_SPEED_SHS;
345#endif
346
347    ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
348    if (ret)
349        return ret;
350
351    mmc_card_set_highspeed(card);
352    card->host->ios.timing = MMC_TIMING_SD_HS;
353    card->host->ops->set_ios(card->host, &card->host->ios);
354
355    return 0;
356}
357
358static int
359csr_sdio_disable_hs(struct mmc_card *card)
360{
361    int ret;
362    u8 speed;
363
364    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
365        return 0;
366
367    if (!card->cccr.high_speed)
368        return 0;
369#if 1
370    ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
371    if (ret)
372        return ret;
373
374    speed &= ~SDIO_SPEED_EHS;
375#else
376    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
377    speed = SDIO_SPEED_SHS; /* clear SDIO_SPEED_EHS */
378#endif
379
380    ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
381    if (ret)
382        return ret;
383
384    card->state &= ~MMC_STATE_HIGHSPEED;
385    card->host->ios.timing = MMC_TIMING_LEGACY;
386    card->host->ops->set_ios(card->host, &card->host->ios);
387
388    return 0;
389}
390
391
392/*
393 * ---------------------------------------------------------------------------
394 * CsrSdioMaxBusClockFrequencySet
395 *
396 * Set the maximum SDIO bus clock speed to use.
397 *
398 * Arguments:
399 * sdio SDIO context pointer
400 * maxFrequency maximum clock speed in Hz
401 *
402 * Returns:
403 * an error code.
404 * ---------------------------------------------------------------------------
405 */
406CsrResult
407CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, u32 maxFrequency)
408{
409    struct sdio_func *func = (struct sdio_func *)function->priv;
410    struct mmc_host *host = func->card->host;
411    struct mmc_ios *ios = &host->ios;
412    unsigned int max_hz;
413    int err;
414    u32 max_khz = maxFrequency/1000;
415
416    if (!max_khz || max_khz > sdio_clock) {
417        max_khz = sdio_clock;
418    }
419
420    _sdio_claim_host(func);
421    max_hz = 1000 * max_khz;
422    if (max_hz > host->f_max) {
423        max_hz = host->f_max;
424    }
425
426    if (max_hz > 25000000) {
427        err = csr_sdio_enable_hs(func->card);
428    } else {
429        err = csr_sdio_disable_hs(func->card);
430    }
431    if (err) {
432        printk(KERN_ERR "SDIO warning: Failed to configure SDIO clock mode\n");
433        _sdio_release_host(func);
434        return CSR_RESULT_SUCCESS;
435    }
436
437    ios->clock = max_hz;
438    host->ops->set_ios(host, ios);
439
440    _sdio_release_host(func);
441
442    return CSR_RESULT_SUCCESS;
443} /* CsrSdioMaxBusClockFrequencySet() */
444
445
446/*
447 * ---------------------------------------------------------------------------
448 * CsrSdioInterruptEnable
449 * CsrSdioInterruptDisable
450 *
451 * Enable or disable the SDIO interrupt.
452 * The driver disables the SDIO interrupt until the i/o thread can
453 * process it.
454 * The SDIO interrupt can be disabled by modifying the SDIO_INT_ENABLE
455 * register in the Card Common Control Register block, but this requires
456 * two CMD52 operations. A better solution is to mask the interrupt at
457 * the host controller.
458 *
459 * Arguments:
460 * sdio SDIO context pointer
461 *
462 * Returns:
463 * Zero on success or a UniFi driver error code.
464 *
465 * ---------------------------------------------------------------------------
466 */
467CsrResult
468CsrSdioInterruptEnable(CsrSdioFunction *function)
469{
470    struct sdio_func *func = (struct sdio_func *)function->priv;
471    int err = 0;
472
473#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
474    sdio_unblock_card_irq(func);
475#else
476    _sdio_claim_host(func);
477    /* Write the Int Enable in CCCR block */
478#ifdef MMC_QUIRK_LENIENT_FN0
479    sdio_f0_writeb(func, 0x3, SDIO_CCCR_IENx, &err);
480#else
481    err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x03, NULL);
482#endif
483    _sdio_release_host(func);
484
485    func_exit();
486    if (err) {
487        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
488        return ConvertSdioToCsrSdioResult(err);
489    }
490#endif
491    return CSR_RESULT_SUCCESS;
492} /* CsrSdioInterruptEnable() */
493
494CsrResult
495CsrSdioInterruptDisable(CsrSdioFunction *function)
496{
497    struct sdio_func *func = (struct sdio_func *)function->priv;
498    int err = 0;
499
500#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
501    sdio_block_card_irq(func);
502#else
503    _sdio_claim_host(func);
504    /* Write the Int Enable in CCCR block */
505#ifdef MMC_QUIRK_LENIENT_FN0
506    sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &err);
507#else
508    err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL);
509#endif
510    _sdio_release_host(func);
511
512    func_exit();
513    if (err) {
514        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
515        return ConvertSdioToCsrSdioResult(err);
516    }
517#endif
518    return CSR_RESULT_SUCCESS;
519} /* CsrSdioInterruptDisable() */
520
521
522void CsrSdioInterruptAcknowledge(CsrSdioFunction *function)
523{
524}
525
526
527/*
528 * ---------------------------------------------------------------------------
529 * CsrSdioFunctionEnable
530 *
531 * Enable i/o on function 1.
532 *
533 * Arguments:
534 * sdio SDIO context pointer
535 *
536 * Returns:
537 * UniFi driver error code.
538 * ---------------------------------------------------------------------------
539 */
540CsrResult
541CsrSdioFunctionEnable(CsrSdioFunction *function)
542{
543    struct sdio_func *func = (struct sdio_func *)function->priv;
544    int err;
545
546    func_enter();
547
548    /* Enable UniFi function 1 (the 802.11 part). */
549    _sdio_claim_host(func);
550    err = sdio_enable_func(func);
551    _sdio_release_host(func);
552    if (err) {
553        unifi_error(NULL, "Failed to enable SDIO function %d\n", func->num);
554    }
555
556    func_exit();
557    return ConvertSdioToCsrSdioResult(err);
558} /* CsrSdioFunctionEnable() */
559
560
561/*
562 * ---------------------------------------------------------------------------
563 * CsrSdioFunctionDisable
564 *
565 * Enable i/o on function 1.
566 *
567 * Arguments:
568 * sdio SDIO context pointer
569 *
570 * Returns:
571 * UniFi driver error code.
572 * ---------------------------------------------------------------------------
573 */
574CsrResult
575CsrSdioFunctionDisable(CsrSdioFunction *function)
576{
577    struct sdio_func *func = (struct sdio_func *)function->priv;
578    int err;
579
580    func_enter();
581
582    /* Disable UniFi function 1 (the 802.11 part). */
583    _sdio_claim_host(func);
584    err = sdio_disable_func(func);
585    _sdio_release_host(func);
586    if (err) {
587        unifi_error(NULL, "Failed to disable SDIO function %d\n", func->num);
588    }
589
590    func_exit();
591    return ConvertSdioToCsrSdioResult(err);
592} /* CsrSdioFunctionDisable() */
593
594
595/*
596 * ---------------------------------------------------------------------------
597 * CsrSdioFunctionActive
598 *
599 * No-op as the bus goes to an active state at the start of every
600 * command.
601 *
602 * Arguments:
603 * sdio SDIO context pointer
604 * ---------------------------------------------------------------------------
605 */
606void
607CsrSdioFunctionActive(CsrSdioFunction *function)
608{
609} /* CsrSdioFunctionActive() */
610
611/*
612 * ---------------------------------------------------------------------------
613 * CsrSdioFunctionIdle
614 *
615 * Set the function as idle.
616 *
617 * Arguments:
618 * sdio SDIO context pointer
619 * ---------------------------------------------------------------------------
620 */
621void
622CsrSdioFunctionIdle(CsrSdioFunction *function)
623{
624} /* CsrSdioFunctionIdle() */
625
626
627/*
628 * ---------------------------------------------------------------------------
629 * CsrSdioPowerOn
630 *
631 * Power on UniFi.
632 *
633 * Arguments:
634 * sdio SDIO context pointer
635 * ---------------------------------------------------------------------------
636 */
637CsrResult
638CsrSdioPowerOn(CsrSdioFunction *function)
639{
640#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
641    struct sdio_func *func = (struct sdio_func *)function->priv;
642    struct mmc_host *host = func->card->host;
643
644    _sdio_claim_host(func);
645    if (!card_is_powered) {
646        mmc_power_restore_host(host);
647        card_is_powered = 1;
648    } else {
649        printk(KERN_INFO "SDIO: Skip power on; card is already powered.\n");
650    }
651    _sdio_release_host(func);
652#endif /* 2.6.32 */
653
654    return CSR_RESULT_SUCCESS;
655} /* CsrSdioPowerOn() */
656
657/*
658 * ---------------------------------------------------------------------------
659 * CsrSdioPowerOff
660 *
661 * Power off UniFi.
662 *
663 * Arguments:
664 * sdio SDIO context pointer
665 * ---------------------------------------------------------------------------
666 */
667void
668CsrSdioPowerOff(CsrSdioFunction *function)
669{
670#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
671    struct sdio_func *func = (struct sdio_func *)function->priv;
672    struct mmc_host *host = func->card->host;
673
674    _sdio_claim_host(func);
675    if (card_is_powered) {
676        mmc_power_save_host(host);
677        card_is_powered = 0;
678    } else {
679        printk(KERN_INFO "SDIO: Skip power off; card is already powered off.\n");
680    }
681    _sdio_release_host(func);
682#endif /* 2.6.32 */
683} /* CsrSdioPowerOff() */
684
685
686static int
687sdio_set_block_size_ignore_first_error(struct sdio_func *func, unsigned blksz)
688{
689    int ret;
690
691    if (blksz > func->card->host->max_blk_size)
692        return -EINVAL;
693
694    if (blksz == 0) {
695        blksz = min(func->max_blksize, func->card->host->max_blk_size);
696        blksz = min(blksz, 512u);
697    }
698
699    /*
700     * Ignore -ERANGE (OUT_OF_RANGE in R5) on the first byte as
701     * the block size may be invalid until both bytes are written.
702     */
703    ret = csr_io_rw_direct(func->card, 1, 0,
704                           SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
705                           blksz & 0xff, NULL);
706    if (ret && ret != -ERANGE)
707        return ret;
708    ret = csr_io_rw_direct(func->card, 1, 0,
709                           SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
710                           (blksz >> 8) & 0xff, NULL);
711    if (ret)
712        return ret;
713    func->cur_blksize = blksz;
714
715    return 0;
716}
717
718CsrResult
719CsrSdioBlockSizeSet(CsrSdioFunction *function, u16 blockSize)
720{
721    struct sdio_func *func = (struct sdio_func *)function->priv;
722    int r = 0;
723
724    /* Module parameter overrides */
725    if (sdio_block_size > -1) {
726        blockSize = sdio_block_size;
727    }
728
729    unifi_trace(NULL, UDBG1, "Set SDIO function block size to %d\n",
730                blockSize);
731
732    _sdio_claim_host(func);
733    r = sdio_set_block_size(func, blockSize);
734    _sdio_release_host(func);
735
736    /*
737     * The MMC driver for kernels prior to 2.6.32 may fail this request
738     * with -ERANGE. In this case use our workaround.
739     */
740    if (r == -ERANGE) {
741        _sdio_claim_host(func);
742        r = sdio_set_block_size_ignore_first_error(func, blockSize);
743        _sdio_release_host(func);
744    }
745    if (r) {
746        unifi_error(NULL, "Error %d setting block size\n", r);
747    }
748
749    /* Determine the achieved block size to pass to the core */
750    function->blockSize = func->cur_blksize;
751
752    return ConvertSdioToCsrSdioResult(r);
753} /* CsrSdioBlockSizeSet() */
754
755
756/*
757 * ---------------------------------------------------------------------------
758 * CsrSdioHardReset
759 *
760 * Hard Resets UniFi is possible.
761 *
762 * Arguments:
763 * sdio SDIO context pointer
764 * ---------------------------------------------------------------------------
765 */
766CsrResult
767CsrSdioHardReset(CsrSdioFunction *function)
768{
769    return CSR_RESULT_FAILURE;
770} /* CsrSdioHardReset() */
771
772
773
774/*
775 * ---------------------------------------------------------------------------
776 * uf_glue_sdio_int_handler
777 *
778 * Interrupt callback function for SDIO interrupts.
779 * This is called in kernel context (i.e. not interrupt context).
780 *
781 * Arguments:
782 * func SDIO context pointer
783 *
784 * Returns:
785 * None.
786 *
787 * Note: Called with host already claimed.
788 * ---------------------------------------------------------------------------
789 */
790static void
791uf_glue_sdio_int_handler(struct sdio_func *func)
792{
793    CsrSdioFunction *sdio_ctx;
794    CsrSdioInterruptDsrCallback func_dsr_callback;
795    int r;
796
797    sdio_ctx = sdio_get_drvdata(func);
798    if (!sdio_ctx) {
799        return;
800    }
801
802#ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
803    /*
804     * Normally, we are not allowed to do any SDIO commands here.
805     * However, this is called in a thread context and with the SDIO lock
806     * so we disable the interrupts here instead of trying to do complicated
807     * things with the SDIO lock.
808     */
809#ifdef MMC_QUIRK_LENIENT_FN0
810    sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &r);
811#else
812    r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL);
813#endif
814    if (r) {
815        printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts %d\n", r);
816    }
817#endif
818
819    /* If the function driver has registered a handler, call it */
820    if (sdio_func_drv && sdio_func_drv->intr) {
821
822        func_dsr_callback = sdio_func_drv->intr(sdio_ctx);
823
824        /* If interrupt handle returns a DSR handle, call it */
825        if (func_dsr_callback) {
826            func_dsr_callback(sdio_ctx);
827        }
828    }
829
830} /* uf_glue_sdio_int_handler() */
831
832
833
834/*
835 * ---------------------------------------------------------------------------
836 * csr_sdio_linux_remove_irq
837 *
838 * Unregister the interrupt handler.
839 * This means that the linux layer can not process interrupts any more.
840 *
841 * Arguments:
842 * sdio SDIO context pointer
843 *
844 * Returns:
845 * Status of the removal.
846 * ---------------------------------------------------------------------------
847 */
848int
849csr_sdio_linux_remove_irq(CsrSdioFunction *function)
850{
851    struct sdio_func *func = (struct sdio_func *)function->priv;
852    int r;
853
854    unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
855
856    sdio_claim_host(func);
857    r = sdio_release_irq(func);
858    sdio_release_host(func);
859
860    return r;
861
862} /* csr_sdio_linux_remove_irq() */
863
864
865/*
866 * ---------------------------------------------------------------------------
867 * csr_sdio_linux_install_irq
868 *
869 * Register the interrupt handler.
870 * This means that the linux layer can process interrupts.
871 *
872 * Arguments:
873 * sdio SDIO context pointer
874 *
875 * Returns:
876 * Status of the removal.
877 * ---------------------------------------------------------------------------
878 */
879int
880csr_sdio_linux_install_irq(CsrSdioFunction *function)
881{
882    struct sdio_func *func = (struct sdio_func *)function->priv;
883    int r;
884
885    unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
886
887    /* Register our interrupt handle */
888    sdio_claim_host(func);
889    r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
890    sdio_release_host(func);
891
892    /* If the interrupt was installed earlier, is fine */
893    if (r == -EBUSY) {
894        r = 0;
895    }
896
897    return r;
898} /* csr_sdio_linux_install_irq() */
899
900#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
901#ifdef CONFIG_PM
902
903/*
904 * Power Management notifier
905 */
906struct uf_sdio_mmc_pm_notifier
907{
908    struct list_head list;
909
910    CsrSdioFunction *sdio_ctx;
911    struct notifier_block pm_notifier;
912};
913
914/* PM notifier list head */
915static struct uf_sdio_mmc_pm_notifier uf_sdio_mmc_pm_notifiers = {
916    .sdio_ctx = NULL,
917};
918
919/*
920 * ---------------------------------------------------------------------------
921 * uf_sdio_mmc_register_pm_notifier
922 * uf_sdio_mmc_unregister_pm_notifier
923 *
924 * Register/unregister for power management events. A list is used to
925 * allow multiple card instances to be supported.
926 *
927 * Arguments:
928 * sdio_ctx - CSR SDIO context to associate PM notifier to
929 *
930 * Returns:
931 * Register function returns NULL on error
932 * ---------------------------------------------------------------------------
933 */
934static struct uf_sdio_mmc_pm_notifier *
935uf_sdio_mmc_register_pm_notifier(CsrSdioFunction *sdio_ctx)
936{
937    /* Allocate notifier context for this card instance */
938    struct uf_sdio_mmc_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_mmc_pm_notifier), GFP_KERNEL);
939
940    if (notifier_ctx)
941    {
942        notifier_ctx->sdio_ctx = sdio_ctx;
943        notifier_ctx->pm_notifier.notifier_call = uf_sdio_mmc_power_event;
944
945        list_add(&notifier_ctx->list, &uf_sdio_mmc_pm_notifiers.list);
946
947        if (register_pm_notifier(&notifier_ctx->pm_notifier)) {
948            printk(KERN_ERR "unifi: register_pm_notifier failed\n");
949        }
950    }
951
952    return notifier_ctx;
953}
954
955static void
956uf_sdio_mmc_unregister_pm_notifier(CsrSdioFunction *sdio_ctx)
957{
958    struct uf_sdio_mmc_pm_notifier *notifier_ctx;
959    struct list_head *node, *q;
960
961    list_for_each_safe(node, q, &uf_sdio_mmc_pm_notifiers.list) {
962        notifier_ctx = list_entry(node, struct uf_sdio_mmc_pm_notifier, list);
963
964        /* If it matches, unregister and free the notifier context */
965        if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx)
966        {
967            if (unregister_pm_notifier(&notifier_ctx->pm_notifier)) {
968                printk(KERN_ERR "unifi: unregister_pm_notifier failed\n");
969            }
970
971            /* Remove from list */
972            notifier_ctx->sdio_ctx = NULL;
973            list_del(node);
974            kfree(notifier_ctx);
975        }
976    }
977}
978
979/*
980 * ---------------------------------------------------------------------------
981 * uf_sdio_mmc_power_event
982 *
983 * Handler for power management events.
984 *
985 * We need to handle suspend/resume events while the userspace is unsuspended
986 * to allow the SME to run its suspend/resume state machines.
987 *
988 * Arguments:
989 * event event ID
990 *
991 * Returns:
992 * Status of the event handling
993 * ---------------------------------------------------------------------------
994 */
995static int
996uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr)
997{
998    struct uf_sdio_mmc_pm_notifier *notifier_ctx = container_of(this,
999                                                                struct uf_sdio_mmc_pm_notifier,
1000                                                                pm_notifier);
1001
1002    /* Call the CSR SDIO function driver's suspend/resume method
1003     * while the userspace is unsuspended.
1004     */
1005    switch (event) {
1006        case PM_POST_HIBERNATION:
1007        case PM_POST_SUSPEND:
1008            printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ );
1009            if (sdio_func_drv && sdio_func_drv->resume) {
1010                sdio_func_drv->resume(notifier_ctx->sdio_ctx);
1011            }
1012            break;
1013
1014        case PM_HIBERNATION_PREPARE:
1015        case PM_SUSPEND_PREPARE:
1016            printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ );
1017            if (sdio_func_drv && sdio_func_drv->suspend) {
1018                sdio_func_drv->suspend(notifier_ctx->sdio_ctx);
1019            }
1020            break;
1021    }
1022    return NOTIFY_DONE;
1023}
1024
1025#endif /* CONFIG_PM */
1026#endif /* 2.6.32 */
1027
1028/*
1029 * ---------------------------------------------------------------------------
1030 * uf_glue_sdio_probe
1031 *
1032 * Card insert callback.
1033 *
1034 * Arguments:
1035 * func Our (glue layer) context pointer.
1036 *
1037 * Returns:
1038 * UniFi driver error code.
1039 * ---------------------------------------------------------------------------
1040 */
1041static int
1042uf_glue_sdio_probe(struct sdio_func *func,
1043                   const struct sdio_device_id *id)
1044{
1045    int instance;
1046    CsrSdioFunction *sdio_ctx;
1047
1048    func_enter();
1049
1050    /* First of all claim the SDIO driver */
1051    sdio_claim_host(func);
1052
1053#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1054    /* Assume that the card is already powered */
1055    card_is_powered = 1;
1056#endif
1057
1058    /* Assumes one card per host, which is true for SDIO */
1059    instance = func->card->host->index;
1060    printk("sdio bus_id: %16s - UniFi card 0x%X inserted\n",
1061           sdio_func_id(func), instance);
1062
1063    /* Allocate context */
1064    sdio_ctx = (CsrSdioFunction *)kmalloc(sizeof(CsrSdioFunction),
1065                                          GFP_KERNEL);
1066    if (sdio_ctx == NULL) {
1067        sdio_release_host(func);
1068        return -ENOMEM;
1069    }
1070
1071    /* Initialise the context */
1072    sdio_ctx->sdioId.manfId = func->vendor;
1073    sdio_ctx->sdioId.cardId = func->device;
1074    sdio_ctx->sdioId.sdioFunction = func->num;
1075    sdio_ctx->sdioId.sdioInterface = func->class;
1076    sdio_ctx->blockSize = func->cur_blksize;
1077    sdio_ctx->priv = (void *)func;
1078    sdio_ctx->features = 0;
1079
1080    /* Module parameter enables byte mode */
1081    if (sdio_byte_mode) {
1082        sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE;
1083    }
1084
1085    if (func->card->host->caps & MMC_CAP_SD_HIGHSPEED) {
1086        unifi_trace(NULL, UDBG1, "MMC_CAP_SD_HIGHSPEED is available\n");
1087    }
1088
1089#ifdef MMC_QUIRK_LENIENT_FN0
1090    func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
1091#endif
1092
1093    /* Pass context to the SDIO driver */
1094    sdio_set_drvdata(func, sdio_ctx);
1095
1096#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1097#ifdef CONFIG_PM
1098    /* Register to get PM events */
1099    if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) {
1100        unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__);
1101    }
1102#endif
1103#endif
1104
1105    /* Register this device with the SDIO function driver */
1106    /* Call the main UniFi driver inserted handler */
1107    if (sdio_func_drv && sdio_func_drv->inserted) {
1108        uf_add_os_device(instance, &func->dev);
1109        sdio_func_drv->inserted(sdio_ctx);
1110    }
1111
1112    /* We have finished, so release the SDIO driver */
1113    sdio_release_host(func);
1114
1115#ifdef ANDROID_BUILD
1116    /* Take the wakelock */
1117    unifi_trace(NULL, UDBG1, "probe: take wake lock\n");
1118    wake_lock(&unifi_sdio_wake_lock);
1119#endif
1120
1121    func_exit();
1122    return 0;
1123} /* uf_glue_sdio_probe() */
1124
1125
1126/*
1127 * ---------------------------------------------------------------------------
1128 * uf_glue_sdio_remove
1129 *
1130 * Card removal callback.
1131 *
1132 * Arguments:
1133 * func Our (glue layer) context pointer.
1134 *
1135 * Returns:
1136 * UniFi driver error code.
1137 * ---------------------------------------------------------------------------
1138 */
1139static void
1140uf_glue_sdio_remove(struct sdio_func *func)
1141{
1142    CsrSdioFunction *sdio_ctx;
1143
1144    sdio_ctx = sdio_get_drvdata(func);
1145    if (!sdio_ctx) {
1146        return;
1147    }
1148
1149    func_enter();
1150
1151    unifi_info(NULL, "UniFi card removed\n");
1152
1153    /* Clean up the SDIO function driver */
1154    if (sdio_func_drv && sdio_func_drv->removed) {
1155        uf_remove_os_device(func->card->host->index);
1156        sdio_func_drv->removed(sdio_ctx);
1157    }
1158
1159#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1160#ifdef CONFIG_PM
1161    /* Unregister for PM events */
1162    uf_sdio_mmc_unregister_pm_notifier(sdio_ctx);
1163#endif
1164#endif
1165
1166    kfree(sdio_ctx);
1167
1168    func_exit();
1169
1170} /* uf_glue_sdio_remove */
1171
1172
1173/*
1174 * SDIO ids *must* be statically declared, so we can't take
1175 * them from the list passed in csr_sdio_register_driver().
1176 */
1177static const struct sdio_device_id unifi_ids[] = {
1178    { SDIO_DEVICE(SDIO_MANF_ID_CSR,SDIO_CARD_ID_UNIFI_3) },
1179    { SDIO_DEVICE(SDIO_MANF_ID_CSR,SDIO_CARD_ID_UNIFI_4) },
1180    { /* end: all zeroes */ },
1181};
1182
1183MODULE_DEVICE_TABLE(sdio, unifi_ids);
1184
1185#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1186#ifdef CONFIG_PM
1187
1188/*
1189 * ---------------------------------------------------------------------------
1190 * uf_glue_sdio_suspend
1191 *
1192 * Card suspend callback. The userspace will already be suspended.
1193 *
1194 * Arguments:
1195 * dev The struct device owned by the MMC driver
1196 *
1197 * Returns:
1198 * None
1199 * ---------------------------------------------------------------------------
1200 */
1201static int
1202uf_glue_sdio_suspend(struct device *dev)
1203{
1204    func_enter();
1205
1206    unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend");
1207
1208    func_exit();
1209    return 0;
1210} /* uf_glue_sdio_suspend */
1211
1212
1213/*
1214 * ---------------------------------------------------------------------------
1215 * uf_glue_sdio_resume
1216 *
1217 * Card resume callback. The userspace will still be suspended.
1218 *
1219 * Arguments:
1220 * dev The struct device owned by the MMC driver
1221 *
1222 * Returns:
1223 * None
1224 * ---------------------------------------------------------------------------
1225 */
1226static int
1227uf_glue_sdio_resume(struct device *dev)
1228{
1229    func_enter();
1230
1231    unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume");
1232
1233#ifdef ANDROID_BUILD
1234    unifi_trace(NULL, UDBG1, "resume: take wakelock\n");
1235    wake_lock(&unifi_sdio_wake_lock);
1236#endif
1237
1238    func_exit();
1239    return 0;
1240
1241} /* uf_glue_sdio_resume */
1242
1243static struct dev_pm_ops unifi_pm_ops = {
1244    .suspend = uf_glue_sdio_suspend,
1245    .resume = uf_glue_sdio_resume,
1246};
1247
1248#define UNIFI_PM_OPS (&unifi_pm_ops)
1249
1250#else
1251
1252#define UNIFI_PM_OPS NULL
1253
1254#endif /* CONFIG_PM */
1255#endif /* 2.6.32 */
1256
1257static struct sdio_driver unifi_driver = {
1258    .probe = uf_glue_sdio_probe,
1259    .remove = uf_glue_sdio_remove,
1260    .name = "unifi",
1261    .id_table = unifi_ids,
1262#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1263    .drv.pm = UNIFI_PM_OPS,
1264#endif /* 2.6.32 */
1265};
1266
1267
1268/*
1269 * ---------------------------------------------------------------------------
1270 * CsrSdioFunctionDriverRegister
1271 * CsrSdioFunctionDriverUnregister
1272 *
1273 * These functions are called from the main module load and unload
1274 * functions. They perform the appropriate operations for the
1275 * linux MMC/SDIO driver.
1276 *
1277 * Arguments:
1278 * sdio_drv Pointer to the function driver's SDIO structure.
1279 *
1280 * Returns:
1281 * None.
1282 * ---------------------------------------------------------------------------
1283 */
1284CsrResult
1285CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
1286{
1287    int r;
1288
1289    printk("UniFi: Using native Linux MMC driver for SDIO.\n");
1290
1291    if (sdio_func_drv) {
1292        unifi_error(NULL, "sdio_mmc: UniFi driver already registered\n");
1293        return CSR_SDIO_RESULT_INVALID_VALUE;
1294    }
1295
1296#ifdef ANDROID_BUILD
1297    wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work");
1298#endif
1299
1300    /* Save the registered driver description */
1301    /*
1302     * FIXME:
1303     * Need a table here to handle a call to register for just one function.
1304     * mmc only allows us to register for the whole device
1305     */
1306    sdio_func_drv = sdio_drv;
1307
1308#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1309#ifdef CONFIG_PM
1310    /* Initialise PM notifier list */
1311    INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list);
1312#endif
1313#endif
1314
1315    /* Register ourself with mmc_core */
1316    r = sdio_register_driver(&unifi_driver);
1317    if (r) {
1318        printk(KERN_ERR "unifi_sdio: Failed to register UniFi SDIO driver: %d\n", r);
1319        return ConvertSdioToCsrSdioResult(r);
1320    }
1321
1322    return CSR_RESULT_SUCCESS;
1323} /* CsrSdioFunctionDriverRegister() */
1324
1325
1326
1327void
1328CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
1329{
1330    printk(KERN_INFO "UniFi: unregister from MMC sdio\n");
1331
1332#ifdef ANDROID_BUILD
1333    wake_lock_destroy(&unifi_sdio_wake_lock);
1334#endif
1335    sdio_unregister_driver(&unifi_driver);
1336
1337    sdio_func_drv = NULL;
1338
1339} /* CsrSdioFunctionDriverUnregister() */
1340
1341

Archive Download this file



interactive