0001
0002
0003
0004 #include <linux/errno.h>
0005 #include <linux/mfd/rohm-generic.h>
0006 #include <linux/module.h>
0007 #include <linux/of.h>
0008 #include <linux/regmap.h>
0009 #include <linux/regulator/driver.h>
0010
0011 static int set_dvs_level(const struct regulator_desc *desc,
0012 struct device_node *np, struct regmap *regmap,
0013 char *prop, unsigned int reg, unsigned int mask,
0014 unsigned int omask, unsigned int oreg)
0015 {
0016 int ret, i;
0017 uint32_t uv;
0018
0019 ret = of_property_read_u32(np, prop, &uv);
0020 if (ret) {
0021 if (ret != -EINVAL)
0022 return ret;
0023 return 0;
0024 }
0025
0026 if (uv == 0) {
0027 if (omask)
0028 return regmap_update_bits(regmap, oreg, omask, 0);
0029 }
0030
0031 if (!mask) {
0032 if (omask)
0033 return regmap_update_bits(regmap, oreg, omask, omask);
0034
0035 return -EINVAL;
0036 }
0037 for (i = 0; i < desc->n_voltages; i++) {
0038
0039 if (desc->linear_range_selectors)
0040 return -EINVAL;
0041 if (desc->n_linear_ranges)
0042 ret = regulator_desc_list_voltage_linear_range(desc, i);
0043 else
0044 ret = regulator_desc_list_voltage_linear(desc, i);
0045 if (ret < 0)
0046 continue;
0047 if (ret == uv) {
0048 i <<= ffs(desc->vsel_mask) - 1;
0049 ret = regmap_update_bits(regmap, reg, mask, i);
0050 if (omask && !ret)
0051 ret = regmap_update_bits(regmap, oreg, omask,
0052 omask);
0053 break;
0054 }
0055 }
0056 return ret;
0057 }
0058
0059 int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
0060 struct device_node *np,
0061 const struct regulator_desc *desc,
0062 struct regmap *regmap)
0063 {
0064 int i, ret = 0;
0065 char *prop;
0066 unsigned int reg, mask, omask, oreg = desc->enable_reg;
0067
0068 for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
0069 int bit;
0070
0071 bit = BIT(i);
0072 if (dvs->level_map & bit) {
0073 switch (bit) {
0074 case ROHM_DVS_LEVEL_RUN:
0075 prop = "rohm,dvs-run-voltage";
0076 reg = dvs->run_reg;
0077 mask = dvs->run_mask;
0078 omask = dvs->run_on_mask;
0079 break;
0080 case ROHM_DVS_LEVEL_IDLE:
0081 prop = "rohm,dvs-idle-voltage";
0082 reg = dvs->idle_reg;
0083 mask = dvs->idle_mask;
0084 omask = dvs->idle_on_mask;
0085 break;
0086 case ROHM_DVS_LEVEL_SUSPEND:
0087 prop = "rohm,dvs-suspend-voltage";
0088 reg = dvs->suspend_reg;
0089 mask = dvs->suspend_mask;
0090 omask = dvs->suspend_on_mask;
0091 break;
0092 case ROHM_DVS_LEVEL_LPSR:
0093 prop = "rohm,dvs-lpsr-voltage";
0094 reg = dvs->lpsr_reg;
0095 mask = dvs->lpsr_mask;
0096 omask = dvs->lpsr_on_mask;
0097 break;
0098 case ROHM_DVS_LEVEL_SNVS:
0099 prop = "rohm,dvs-snvs-voltage";
0100 reg = dvs->snvs_reg;
0101 mask = dvs->snvs_mask;
0102 omask = dvs->snvs_on_mask;
0103 break;
0104 default:
0105 return -EINVAL;
0106 }
0107 ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
0108 omask, oreg);
0109 }
0110 }
0111 return ret;
0112 }
0113 EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
0114
0115
0116
0117
0118
0119
0120
0121 int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev,
0122 unsigned int sel)
0123 {
0124 if (rdev->desc->ops->is_enabled(rdev))
0125 return -EBUSY;
0126
0127 return regulator_set_voltage_sel_regmap(rdev, sel);
0128 }
0129 EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);
0130
0131 MODULE_LICENSE("GPL v2");
0132 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
0133 MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");