Commit 5c13941acc513669c7d07b28789c3f9ba66ddddf

Authored by David Brownell
Committed by Liam Girdwood
1 parent 66b659e685

MMC: regulator utilities

Glue between MMC and regulator stacks ... verified with
some OMAP3 boards using adjustable and configured-as-fixed
regulators on several MMC controllers.

These calls are intended to be used by MMC host adapters
using at least one regulator per host.  Examples include
slots with regulators supporting multiple voltages and
ones using multiple voltage rails (e.g. DAT4..DAT7 using a
separate supply, or a split rail chip like certain SDIO
WLAN or eMMC solutions).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>

Showing 2 changed files with 105 additions and 0 deletions Side-by-side Diff

drivers/mmc/core/core.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/leds.h>
22 22 #include <linux/scatterlist.h>
23 23 #include <linux/log2.h>
  24 +#include <linux/regulator/consumer.h>
24 25  
25 26 #include <linux/mmc/card.h>
26 27 #include <linux/mmc/host.h>
... ... @@ -522,6 +523,105 @@
522 523 return mask;
523 524 }
524 525 EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
  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 + */
  538 +int 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 +}
  562 +EXPORT_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 + */
  575 +int 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 +}
  622 +EXPORT_SYMBOL(mmc_regulator_set_ocr);
  623 +
  624 +#endif
525 625  
526 626 /*
527 627 * Mask off any voltages we don't support and select
include/linux/mmc/host.h
... ... @@ -192,5 +192,10 @@
192 192 wake_up_process(host->sdio_irq_thread);
193 193 }
194 194  
  195 +struct regulator;
  196 +
  197 +int mmc_regulator_get_ocrmask(struct regulator *supply);
  198 +int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
  199 +
195 200 #endif