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 | |
| parent | fa64efa1f2a0672767ad0753a6e4bfa4bcc77b87 (diff) | |
sdio: read and decode interesting parts of the CCCR
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
| -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 | ||
