diff options
-rw-r--r-- | drivers/mmc/core/sdio.c | 63 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 11 |
2 files changed, 74 insertions, 0 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 444328581cec..7ce3e3104d21 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/mmc/host.h> | 14 | #include <linux/mmc/host.h> |
15 | #include <linux/mmc/card.h> | 15 | #include <linux/mmc/card.h> |
16 | #include <linux/mmc/sdio.h> | ||
16 | #include <linux/mmc/sdio_func.h> | 17 | #include <linux/mmc/sdio_func.h> |
17 | 18 | ||
18 | #include "core.h" | 19 | #include "core.h" |
@@ -39,6 +40,61 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn) | |||
39 | return 0; | 40 | return 0; |
40 | } | 41 | } |
41 | 42 | ||
43 | static int sdio_read_cccr(struct mmc_card *card) | ||
44 | { | ||
45 | int ret; | ||
46 | int cccr_vsn; | ||
47 | unsigned char data; | ||
48 | |||
49 | memset(&card->cccr, 0, sizeof(struct sdio_cccr)); | ||
50 | |||
51 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data); | ||
52 | if (ret) | ||
53 | goto out; | ||
54 | |||
55 | cccr_vsn = data & 0x0f; | ||
56 | |||
57 | if (cccr_vsn > SDIO_CCCR_REV_1_20) { | ||
58 | printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n", | ||
59 | mmc_hostname(card->host), cccr_vsn); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | card->cccr.sdio_vsn = (data & 0xf0) >> 4; | ||
64 | |||
65 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data); | ||
66 | if (ret) | ||
67 | goto out; | ||
68 | |||
69 | if (data & SDIO_CCCR_CAP_SMB) | ||
70 | card->cccr.multi_block = 1; | ||
71 | if (data & SDIO_CCCR_CAP_LSC) | ||
72 | card->cccr.low_speed = 1; | ||
73 | if (data & SDIO_CCCR_CAP_4BLS) | ||
74 | card->cccr.wide_bus = 1; | ||
75 | |||
76 | if (cccr_vsn >= SDIO_CCCR_REV_1_10) { | ||
77 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data); | ||
78 | if (ret) | ||
79 | goto out; | ||
80 | |||
81 | if (data & SDIO_POWER_SMPC) | ||
82 | card->cccr.high_power = 1; | ||
83 | } | ||
84 | |||
85 | if (cccr_vsn >= SDIO_CCCR_REV_1_20) { | ||
86 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data); | ||
87 | if (ret) | ||
88 | goto out; | ||
89 | |||
90 | if (data & SDIO_SPEED_SHS) | ||
91 | card->cccr.high_speed = 1; | ||
92 | } | ||
93 | |||
94 | out: | ||
95 | return ret; | ||
96 | } | ||
97 | |||
42 | /* | 98 | /* |
43 | * Host is being removed. Free up the current card. | 99 | * Host is being removed. Free up the current card. |
44 | */ | 100 | */ |
@@ -181,6 +237,13 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
181 | goto remove; | 237 | goto remove; |
182 | 238 | ||
183 | /* | 239 | /* |
240 | * Read the common registers. | ||
241 | */ | ||
242 | err = sdio_read_cccr(card); | ||
243 | if (err) | ||
244 | goto remove; | ||
245 | |||
246 | /* | ||
184 | * Initialize (but don't add) all present functions. | 247 | * Initialize (but don't add) all present functions. |
185 | */ | 248 | */ |
186 | for (i = 0;i < funcs;i++) { | 249 | for (i = 0;i < funcs;i++) { |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 9f5f74482d98..520d9d29b3b2 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -55,6 +55,16 @@ struct sd_switch_caps { | |||
55 | unsigned int hs_max_dtr; | 55 | unsigned int hs_max_dtr; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct sdio_cccr { | ||
59 | unsigned int sdio_vsn; | ||
60 | unsigned int sd_vsn; | ||
61 | unsigned int multi_block:1, | ||
62 | low_speed:1, | ||
63 | wide_bus:1, | ||
64 | high_power:1, | ||
65 | high_speed:1; | ||
66 | }; | ||
67 | |||
58 | struct mmc_host; | 68 | struct mmc_host; |
59 | struct sdio_func; | 69 | struct sdio_func; |
60 | 70 | ||
@@ -87,6 +97,7 @@ struct mmc_card { | |||
87 | struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ | 97 | struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ |
88 | 98 | ||
89 | unsigned int sdio_funcs; /* number of SDIO functions */ | 99 | unsigned int sdio_funcs; /* number of SDIO functions */ |
100 | struct sdio_cccr cccr; /* common card info */ | ||
90 | struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */ | 101 | struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */ |
91 | }; | 102 | }; |
92 | 103 | ||