diff options
-rw-r--r-- | drivers/mmc/core/sd.c | 68 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 4 |
2 files changed, 62 insertions, 10 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index b0cd285d272a..8285842f19e9 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -189,6 +189,9 @@ static int mmc_decode_scr(struct mmc_card *card) | |||
189 | 189 | ||
190 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); | 190 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); |
191 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); | 191 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); |
192 | if (scr->sda_vsn == SCR_SPEC_VER_2) | ||
193 | /* Check if Physical Layer Spec v3.0 is supported */ | ||
194 | scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1); | ||
192 | 195 | ||
193 | if (UNSTUFF_BITS(resp, 55, 1)) | 196 | if (UNSTUFF_BITS(resp, 55, 1)) |
194 | card->erased_byte = 0xFF; | 197 | card->erased_byte = 0xFF; |
@@ -274,29 +277,74 @@ static int mmc_read_switch(struct mmc_card *card) | |||
274 | status = kmalloc(64, GFP_KERNEL); | 277 | status = kmalloc(64, GFP_KERNEL); |
275 | if (!status) { | 278 | if (!status) { |
276 | printk(KERN_ERR "%s: could not allocate a buffer for " | 279 | printk(KERN_ERR "%s: could not allocate a buffer for " |
277 | "switch capabilities.\n", mmc_hostname(card->host)); | 280 | "switch capabilities.\n", |
281 | mmc_hostname(card->host)); | ||
278 | return -ENOMEM; | 282 | return -ENOMEM; |
279 | } | 283 | } |
280 | 284 | ||
285 | /* Find out the supported Bus Speed Modes. */ | ||
281 | err = mmc_sd_switch(card, 0, 0, 1, status); | 286 | err = mmc_sd_switch(card, 0, 0, 1, status); |
282 | if (err) { | 287 | if (err) { |
283 | /* If the host or the card can't do the switch, | 288 | /* |
284 | * fail more gracefully. */ | 289 | * If the host or the card can't do the switch, |
285 | if ((err != -EINVAL) | 290 | * fail more gracefully. |
286 | && (err != -ENOSYS) | 291 | */ |
287 | && (err != -EFAULT)) | 292 | if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) |
288 | goto out; | 293 | goto out; |
289 | 294 | ||
290 | printk(KERN_WARNING "%s: problem reading switch " | 295 | printk(KERN_WARNING "%s: problem reading Bus Speed modes.\n", |
291 | "capabilities, performance might suffer.\n", | ||
292 | mmc_hostname(card->host)); | 296 | mmc_hostname(card->host)); |
293 | err = 0; | 297 | err = 0; |
294 | 298 | ||
295 | goto out; | 299 | goto out; |
296 | } | 300 | } |
297 | 301 | ||
298 | if (status[13] & 0x02) | 302 | if (card->scr.sda_spec3) { |
299 | card->sw_caps.hs_max_dtr = 50000000; | 303 | card->sw_caps.sd3_bus_mode = status[13]; |
304 | |||
305 | /* Find out Driver Strengths supported by the card */ | ||
306 | err = mmc_sd_switch(card, 0, 2, 1, status); | ||
307 | if (err) { | ||
308 | /* | ||
309 | * If the host or the card can't do the switch, | ||
310 | * fail more gracefully. | ||
311 | */ | ||
312 | if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) | ||
313 | goto out; | ||
314 | |||
315 | printk(KERN_WARNING "%s: problem reading " | ||
316 | "Driver Strength.\n", | ||
317 | mmc_hostname(card->host)); | ||
318 | err = 0; | ||
319 | |||
320 | goto out; | ||
321 | } | ||
322 | |||
323 | card->sw_caps.sd3_drv_type = status[9]; | ||
324 | |||
325 | /* Find out Current Limits supported by the card */ | ||
326 | err = mmc_sd_switch(card, 0, 3, 1, status); | ||
327 | if (err) { | ||
328 | /* | ||
329 | * If the host or the card can't do the switch, | ||
330 | * fail more gracefully. | ||
331 | */ | ||
332 | if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) | ||
333 | goto out; | ||
334 | |||
335 | printk(KERN_WARNING "%s: problem reading " | ||
336 | "Current Limit.\n", | ||
337 | mmc_hostname(card->host)); | ||
338 | err = 0; | ||
339 | |||
340 | goto out; | ||
341 | } | ||
342 | |||
343 | card->sw_caps.sd3_curr_limit = status[7]; | ||
344 | } else { | ||
345 | if (status[13] & 0x02) | ||
346 | card->sw_caps.hs_max_dtr = 50000000; | ||
347 | } | ||
300 | 348 | ||
301 | out: | 349 | out: |
302 | kfree(status); | 350 | kfree(status); |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 72a98681ef47..56f4d9234a66 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -67,6 +67,7 @@ struct mmc_ext_csd { | |||
67 | 67 | ||
68 | struct sd_scr { | 68 | struct sd_scr { |
69 | unsigned char sda_vsn; | 69 | unsigned char sda_vsn; |
70 | unsigned char sda_spec3; | ||
70 | unsigned char bus_widths; | 71 | unsigned char bus_widths; |
71 | #define SD_SCR_BUS_WIDTH_1 (1<<0) | 72 | #define SD_SCR_BUS_WIDTH_1 (1<<0) |
72 | #define SD_SCR_BUS_WIDTH_4 (1<<2) | 73 | #define SD_SCR_BUS_WIDTH_4 (1<<2) |
@@ -80,6 +81,9 @@ struct sd_ssr { | |||
80 | 81 | ||
81 | struct sd_switch_caps { | 82 | struct sd_switch_caps { |
82 | unsigned int hs_max_dtr; | 83 | unsigned int hs_max_dtr; |
84 | unsigned int sd3_bus_mode; | ||
85 | unsigned int sd3_drv_type; | ||
86 | unsigned int sd3_curr_limit; | ||
83 | }; | 87 | }; |
84 | 88 | ||
85 | struct sdio_cccr { | 89 | struct sdio_cccr { |