~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/mmc/core/quirks.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  This file contains work-arounds for many known sdio hardware
3
 
 *  bugs.
 
2
 *  This file contains work-arounds for many known SD/MMC
 
3
 *  and SDIO hardware bugs.
4
4
 *
 
5
 *  Copyright (c) 2011 Andrei Warkentin <andreiw@motorola.com>
5
6
 *  Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
6
7
 *  Inspired from pci fixup code:
7
8
 *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
11
12
#include <linux/types.h>
12
13
#include <linux/kernel.h>
13
14
#include <linux/mmc/card.h>
14
 
#include <linux/mod_devicetable.h>
15
 
 
16
 
/*
17
 
 *  The world is not perfect and supplies us with broken mmc/sdio devices.
18
 
 *  For at least a part of these bugs we need a work-around
19
 
 */
20
 
 
21
 
struct mmc_fixup {
22
 
        u16 vendor, device;     /* You can use SDIO_ANY_ID here of course */
23
 
        void (*vendor_fixup)(struct mmc_card *card, int data);
24
 
        int data;
25
 
};
26
 
 
27
 
/*
28
 
 * This hook just adds a quirk unconditionnally
29
 
 */
30
 
static void __maybe_unused add_quirk(struct mmc_card *card, int data)
31
 
{
32
 
        card->quirks |= data;
33
 
}
34
 
 
35
 
/*
36
 
 * This hook just removes a quirk unconditionnally
37
 
 */
38
 
static void __maybe_unused remove_quirk(struct mmc_card *card, int data)
39
 
{
40
 
        card->quirks &= ~data;
41
 
}
 
15
 
 
16
#ifndef SDIO_VENDOR_ID_TI
 
17
#define SDIO_VENDOR_ID_TI               0x0097
 
18
#endif
 
19
 
 
20
#ifndef SDIO_DEVICE_ID_TI_WL1271
 
21
#define SDIO_DEVICE_ID_TI_WL1271        0x4076
 
22
#endif
42
23
 
43
24
/*
44
25
 * This hook just adds a quirk for all sdio devices
49
30
                card->quirks |= data;
50
31
}
51
32
 
52
 
#ifndef SDIO_VENDOR_ID_TI
53
 
#define SDIO_VENDOR_ID_TI               0x0097
54
 
#endif
55
 
 
56
 
#ifndef SDIO_DEVICE_ID_TI_WL1271
57
 
#define SDIO_DEVICE_ID_TI_WL1271        0x4076
58
 
#endif
59
 
 
60
33
static const struct mmc_fixup mmc_fixup_methods[] = {
61
34
        /* by default sdio devices are considered CLK_GATING broken */
62
35
        /* good cards will be whitelisted as they are tested */
63
 
        { SDIO_ANY_ID, SDIO_ANY_ID,
64
 
                add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING },
65
 
        { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
66
 
                remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING },
67
 
        { 0 }
 
36
        SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID,
 
37
                   add_quirk_for_sdio_devices,
 
38
                   MMC_QUIRK_BROKEN_CLK_GATING),
 
39
 
 
40
        SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
 
41
                   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
 
42
 
 
43
        SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
 
44
                   add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
 
45
 
 
46
        SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
 
47
                   add_quirk, MMC_QUIRK_DISABLE_CD),
 
48
 
 
49
        END_FIXUP
68
50
};
69
51
 
70
 
void mmc_fixup_device(struct mmc_card *card)
 
52
void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
71
53
{
72
54
        const struct mmc_fixup *f;
73
 
 
74
 
        for (f = mmc_fixup_methods; f->vendor_fixup; f++) {
75
 
                if ((f->vendor == card->cis.vendor
76
 
                     || f->vendor == (u16) SDIO_ANY_ID) &&
77
 
                    (f->device == card->cis.device
78
 
                     || f->device == (u16) SDIO_ANY_ID)) {
 
55
        u64 rev = cid_rev_card(card);
 
56
 
 
57
        /* Non-core specific workarounds. */
 
58
        if (!table)
 
59
                table = mmc_fixup_methods;
 
60
 
 
61
        for (f = table; f->vendor_fixup; f++) {
 
62
                if ((f->manfid == CID_MANFID_ANY ||
 
63
                     f->manfid == card->cid.manfid) &&
 
64
                    (f->oemid == CID_OEMID_ANY ||
 
65
                     f->oemid == card->cid.oemid) &&
 
66
                    (f->name == CID_NAME_ANY ||
 
67
                     !strncmp(f->name, card->cid.prod_name,
 
68
                              sizeof(card->cid.prod_name))) &&
 
69
                    (f->cis_vendor == card->cis.vendor ||
 
70
                     f->cis_vendor == (u16) SDIO_ANY_ID) &&
 
71
                    (f->cis_device == card->cis.device ||
 
72
                     f->cis_device == (u16) SDIO_ANY_ID) &&
 
73
                    rev >= f->rev_start && rev <= f->rev_end) {
79
74
                        dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
80
75
                        f->vendor_fixup(card, f->data);
81
76
                }