diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2007-06-11 14:25:43 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-09-23 14:12:18 -0400 |
commit | 35c66c19088bddb11110c124bad8abd4441a8421 (patch) | |
tree | 54f62d67396b50716945d7ef321097715bcc3365 /drivers/mmc/core | |
parent | fa64efa1f2a0672767ad0753a6e4bfa4bcc77b87 (diff) |
sdio: read and decode interesting parts of the CCCR
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/sdio.c | 63 |
1 files changed, 63 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++) { |