aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/core.c77
-rw-r--r--drivers/mmc/core/mmc.c18
2 files changed, 91 insertions, 4 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f7284b905eb3..df6ce4a06cf3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -20,6 +20,7 @@
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/leds.h> 21#include <linux/leds.h>
22#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
23#include <linux/log2.h>
23 24
24#include <linux/mmc/card.h> 25#include <linux/mmc/card.h>
25#include <linux/mmc/host.h> 26#include <linux/mmc/host.h>
@@ -448,6 +449,80 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
448 mmc_set_ios(host); 449 mmc_set_ios(host);
449} 450}
450 451
452/**
453 * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
454 * @vdd: voltage (mV)
455 * @low_bits: prefer low bits in boundary cases
456 *
457 * This function returns the OCR bit number according to the provided @vdd
458 * value. If conversion is not possible a negative errno value returned.
459 *
460 * Depending on the @low_bits flag the function prefers low or high OCR bits
461 * on boundary voltages. For example,
462 * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
463 * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
464 *
465 * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
466 */
467static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
468{
469 const int max_bit = ilog2(MMC_VDD_35_36);
470 int bit;
471
472 if (vdd < 1650 || vdd > 3600)
473 return -EINVAL;
474
475 if (vdd >= 1650 && vdd <= 1950)
476 return ilog2(MMC_VDD_165_195);
477
478 if (low_bits)
479 vdd -= 1;
480
481 /* Base 2000 mV, step 100 mV, bit's base 8. */
482 bit = (vdd - 2000) / 100 + 8;
483 if (bit > max_bit)
484 return max_bit;
485 return bit;
486}
487
488/**
489 * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
490 * @vdd_min: minimum voltage value (mV)
491 * @vdd_max: maximum voltage value (mV)
492 *
493 * This function returns the OCR mask bits according to the provided @vdd_min
494 * and @vdd_max values. If conversion is not possible the function returns 0.
495 *
496 * Notes wrt boundary cases:
497 * This function sets the OCR bits for all boundary voltages, for example
498 * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
499 * MMC_VDD_34_35 mask.
500 */
501u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
502{
503 u32 mask = 0;
504
505 if (vdd_max < vdd_min)
506 return 0;
507
508 /* Prefer high bits for the boundary vdd_max values. */
509 vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
510 if (vdd_max < 0)
511 return 0;
512
513 /* Prefer low bits for the boundary vdd_min values. */
514 vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
515 if (vdd_min < 0)
516 return 0;
517
518 /* Fill the mask, from max bit to min bit. */
519 while (vdd_max >= vdd_min)
520 mask |= 1 << vdd_max--;
521
522 return mask;
523}
524EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
525
451/* 526/*
452 * Mask off any voltages we don't support and select 527 * Mask off any voltages we don't support and select
453 * the lowest voltage 528 * the lowest voltage
@@ -467,6 +542,8 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
467 host->ios.vdd = bit; 542 host->ios.vdd = bit;
468 mmc_set_ios(host); 543 mmc_set_ios(host);
469 } else { 544 } else {
545 pr_warning("%s: host doesn't support card's voltages\n",
546 mmc_hostname(host));
470 ocr = 0; 547 ocr = 0;
471 } 548 }
472 549
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index fdd7c760be8c..c232d11a7ed4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -434,13 +434,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
434 * Activate wide bus (if supported). 434 * Activate wide bus (if supported).
435 */ 435 */
436 if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && 436 if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
437 (host->caps & MMC_CAP_4_BIT_DATA)) { 437 (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
438 unsigned ext_csd_bit, bus_width;
439
440 if (host->caps & MMC_CAP_8_BIT_DATA) {
441 ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
442 bus_width = MMC_BUS_WIDTH_8;
443 } else {
444 ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
445 bus_width = MMC_BUS_WIDTH_4;
446 }
447
438 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 448 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
439 EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); 449 EXT_CSD_BUS_WIDTH, ext_csd_bit);
450
440 if (err) 451 if (err)
441 goto free_card; 452 goto free_card;
442 453
443 mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); 454 mmc_set_bus_width(card->host, bus_width);
444 } 455 }
445 456
446 if (!oldcard) 457 if (!oldcard)
@@ -624,4 +635,3 @@ err:
624 635
625 return err; 636 return err;
626} 637}
627