aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/core.c100
-rw-r--r--include/linux/mmc/host.h5
2 files changed, 105 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index df6ce4a06cf3..1445ea8f10a6 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -21,6 +21,7 @@
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#include <linux/log2.h>
24#include <linux/regulator/consumer.h>
24 25
25#include <linux/mmc/card.h> 26#include <linux/mmc/card.h>
26#include <linux/mmc/host.h> 27#include <linux/mmc/host.h>
@@ -523,6 +524,105 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
523} 524}
524EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); 525EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
525 526
527#ifdef CONFIG_REGULATOR
528
529/**
530 * mmc_regulator_get_ocrmask - return mask of supported voltages
531 * @supply: regulator to use
532 *
533 * This returns either a negative errno, or a mask of voltages that
534 * can be provided to MMC/SD/SDIO devices using the specified voltage
535 * regulator. This would normally be called before registering the
536 * MMC host adapter.
537 */
538int mmc_regulator_get_ocrmask(struct regulator *supply)
539{
540 int result = 0;
541 int count;
542 int i;
543
544 count = regulator_count_voltages(supply);
545 if (count < 0)
546 return count;
547
548 for (i = 0; i < count; i++) {
549 int vdd_uV;
550 int vdd_mV;
551
552 vdd_uV = regulator_list_voltage(supply, i);
553 if (vdd_uV <= 0)
554 continue;
555
556 vdd_mV = vdd_uV / 1000;
557 result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
558 }
559
560 return result;
561}
562EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
563
564/**
565 * mmc_regulator_set_ocr - set regulator to match host->ios voltage
566 * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
567 * @supply: regulator to use
568 *
569 * Returns zero on success, else negative errno.
570 *
571 * MMC host drivers may use this to enable or disable a regulator using
572 * a particular supply voltage. This would normally be called from the
573 * set_ios() method.
574 */
575int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
576{
577 int result = 0;
578 int min_uV, max_uV;
579 int enabled;
580
581 enabled = regulator_is_enabled(supply);
582 if (enabled < 0)
583 return enabled;
584
585 if (vdd_bit) {
586 int tmp;
587 int voltage;
588
589 /* REVISIT mmc_vddrange_to_ocrmask() may have set some
590 * bits this regulator doesn't quite support ... don't
591 * be too picky, most cards and regulators are OK with
592 * a 0.1V range goof (it's a small error percentage).
593 */
594 tmp = vdd_bit - ilog2(MMC_VDD_165_195);
595 if (tmp == 0) {
596 min_uV = 1650 * 1000;
597 max_uV = 1950 * 1000;
598 } else {
599 min_uV = 1900 * 1000 + tmp * 100 * 1000;
600 max_uV = min_uV + 100 * 1000;
601 }
602
603 /* avoid needless changes to this voltage; the regulator
604 * might not allow this operation
605 */
606 voltage = regulator_get_voltage(supply);
607 if (voltage < 0)
608 result = voltage;
609 else if (voltage < min_uV || voltage > max_uV)
610 result = regulator_set_voltage(supply, min_uV, max_uV);
611 else
612 result = 0;
613
614 if (result == 0 && !enabled)
615 result = regulator_enable(supply);
616 } else if (enabled) {
617 result = regulator_disable(supply);
618 }
619
620 return result;
621}
622EXPORT_SYMBOL(mmc_regulator_set_ocr);
623
624#endif
625
526/* 626/*
527 * Mask off any voltages we don't support and select 627 * Mask off any voltages we don't support and select
528 * the lowest voltage 628 * the lowest voltage
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 4e457256bd33..3e7615e9087e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -192,5 +192,10 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
192 wake_up_process(host->sdio_irq_thread); 192 wake_up_process(host->sdio_irq_thread);
193} 193}
194 194
195struct regulator;
196
197int mmc_regulator_get_ocrmask(struct regulator *supply);
198int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
199
195#endif 200#endif
196 201