aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/sd.c')
-rw-r--r--drivers/mmc/core/sd.c68
1 files changed, 58 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
301out: 349out:
302 kfree(status); 350 kfree(status);