Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2020 ROHM Semiconductors
  3
  4#include <linux/errno.h>
  5#include <linux/mfd/rohm-generic.h>
  6#include <linux/module.h>
  7#include <linux/of.h>
  8#include <linux/regmap.h>
  9#include <linux/regulator/driver.h>
 10
 11static int set_dvs_level(const struct regulator_desc *desc,
 12			 struct device_node *np, struct regmap *regmap,
 13			 char *prop, unsigned int reg, unsigned int mask,
 14			 unsigned int omask, unsigned int oreg)
 15{
 16	int ret, i;
 17	uint32_t uv;
 18
 19	ret = of_property_read_u32(np, prop, &uv);
 20	if (ret) {
 21		if (ret != -EINVAL)
 22			return ret;
 23		return 0;
 24	}
 25	/* If voltage is set to 0 => disable */
 26	if (uv == 0) {
 27		if (omask)
 28			return regmap_update_bits(regmap, oreg, omask, 0);
 29	}
 30	/* Some setups don't allow setting own voltage but do allow enabling */
 31	if (!mask) {
 32		if (omask)
 33			return regmap_update_bits(regmap, oreg, omask, omask);
 34
 35		return -EINVAL;
 36	}
 37	for (i = 0; i < desc->n_voltages; i++) {
 38		/* NOTE to next hacker - Does not support pickable ranges */
 39		if (desc->linear_range_selectors_bitfield)
 40			return -EINVAL;
 41		if (desc->n_linear_ranges)
 42			ret = regulator_desc_list_voltage_linear_range(desc, i);
 43		else
 44			ret = regulator_desc_list_voltage_linear(desc, i);
 45		if (ret < 0)
 46			continue;
 47		if (ret == uv) {
 48			i <<= ffs(desc->vsel_mask) - 1;
 49
 50			ret = regmap_update_bits(regmap, reg, mask, i);
 51			if (omask && !ret)
 52				ret = regmap_update_bits(regmap, oreg, omask,
 53							 omask);
 54			break;
 55		}
 56	}
 57	if (i == desc->n_voltages)
 58		pr_warn("Unsupported %s voltage %u\n", prop, uv);
 59
 60	return ret;
 61}
 62
 63int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
 64			  struct device_node *np,
 65			  const struct regulator_desc *desc,
 66			  struct regmap *regmap)
 67{
 68	int i, ret = 0;
 69	char *prop;
 70	unsigned int reg, mask, omask, oreg = desc->enable_reg;
 71
 72	for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
 73		int bit;
 74
 75		bit = BIT(i);
 76		if (dvs->level_map & bit) {
 77			switch (bit) {
 78			case ROHM_DVS_LEVEL_RUN:
 79				prop = "rohm,dvs-run-voltage";
 80				reg = dvs->run_reg;
 81				mask = dvs->run_mask;
 82				omask = dvs->run_on_mask;
 83				break;
 84			case ROHM_DVS_LEVEL_IDLE:
 85				prop = "rohm,dvs-idle-voltage";
 86				reg = dvs->idle_reg;
 87				mask = dvs->idle_mask;
 88				omask = dvs->idle_on_mask;
 89				break;
 90			case ROHM_DVS_LEVEL_SUSPEND:
 91				prop = "rohm,dvs-suspend-voltage";
 92				reg = dvs->suspend_reg;
 93				mask = dvs->suspend_mask;
 94				omask = dvs->suspend_on_mask;
 95				break;
 96			case ROHM_DVS_LEVEL_LPSR:
 97				prop = "rohm,dvs-lpsr-voltage";
 98				reg = dvs->lpsr_reg;
 99				mask = dvs->lpsr_mask;
100				omask = dvs->lpsr_on_mask;
101				break;
102			case ROHM_DVS_LEVEL_SNVS:
103				prop = "rohm,dvs-snvs-voltage";
104				reg = dvs->snvs_reg;
105				mask = dvs->snvs_mask;
106				omask = dvs->snvs_on_mask;
107				break;
108			default:
109				return -EINVAL;
110			}
111			ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
112					    omask, oreg);
113		}
114	}
115	return ret;
116}
117EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
118
119/*
120 * Few ROHM PMIC ICs have constrains on voltage changing:
121 * BD71837 - only buck 1-4 voltages can be changed when they are enabled.
122 * Other bucks and all LDOs must be disabled when voltage is changed.
123 * BD96801 - LDO voltage levels can be changed when LDOs are disabled.
124 */
125int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev,
126					      unsigned int sel)
127{
128	if (rdev->desc->ops->is_enabled(rdev))
129		return -EBUSY;
130
131	return regulator_set_voltage_sel_regmap(rdev, sel);
132}
133EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);
134
135MODULE_LICENSE("GPL v2");
136MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
137MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");