diff options
author | Haijun Zhang <Haijun.Zhang@freescale.com> | 2013-09-16 11:25:26 (GMT) |
---|---|---|
committer | Rivera Jose-B46482 <German.Rivera@freescale.com> | 2013-09-17 14:20:55 (GMT) |
commit | 356c21aec7dcc9046d27c43323cf031e794c4a75 (patch) | |
tree | 028f39e33df99ea4e2e3b036fb519d54261638ab /drivers/mmc/core | |
parent | 7e3ab14a24354361b8b4f0b2588188137980b9b0 (diff) | |
download | linux-fsl-qoriq-356c21aec7dcc9046d27c43323cf031e794c4a75.tar.xz |
mmc: Add support to get voltage from device-tree
Add function to support get voltage from device-tree.
If there are voltage-range specified in device-tree node, this function
will parse it and return the available voltage mask.
Signed-off-by: Haijun Zhang <haijun.zhang@freescale.com>
Change-Id: I3ec8dd6cb0c628ada3533163c602c9b752a45657
Reviewed-on: http://git.am.freescale.net:8181/4764
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Xie Xiaobo-R63061 <X.Xie@freescale.com>
Reviewed-by: Rivera Jose-B46482 <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/core.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e74504e..395e558 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -27,6 +27,7 @@ #include <linux/fault-inject.h> #include <linux/random.h> #include <linux/slab.h> +#include <linux/of.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -1068,6 +1069,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max) } EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); +#ifdef CONFIG_OF + +/** + * mmc_of_parse_voltage - return mask of supported voltages + * @np: The device node need to be parsed. + * @mask: mask of voltages available for MMC/SD/SDIO + * + * 1. Return zero on success. + * 2. Return negative errno: voltage-range is invalid. + */ +int mmc_of_parse_voltage(struct device_node *np, u32 *mask) +{ + const u32 *voltage_ranges; + int num_ranges, i; + + voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); + num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; + if (!voltage_ranges || !num_ranges) { + pr_info("%s: voltage-ranges unspecified\n", np->full_name); + return -EINVAL; + } + + for (i = 0; i < num_ranges; i++) { + const int j = i * 2; + u32 ocr_mask; + + ocr_mask = mmc_vddrange_to_ocrmask( + be32_to_cpu(voltage_ranges[j]), + be32_to_cpu(voltage_ranges[j + 1])); + if (!ocr_mask) { + pr_err("%s: voltage-range #%d is invalid\n", + np->full_name, i); + return -EINVAL; + } + *mask |= ocr_mask; + } + + return 0; +} +EXPORT_SYMBOL(mmc_of_parse_voltage); + +#endif /* CONFIG_OF */ + #ifdef CONFIG_REGULATOR /** |